Author: Helena Kotas Date: 2025-05-15T19:49:29-07:00 New Revision: f95f3030e595b76a3aa0295997e7dcf865c28796
URL: https://github.com/llvm/llvm-project/commit/f95f3030e595b76a3aa0295997e7dcf865c28796 DIFF: https://github.com/llvm/llvm-project/commit/f95f3030e595b76a3aa0295997e7dcf865c28796.diff LOG: [HLSL] Implicit resource binding for cbuffers (#139022) Constant buffers defined with the `cbuffer` keyword do not have a constructor. Instead, the call to initialize the resource handle based on its binding is generated in codegen. This change adds initialization of `cbuffer` handles that have implicit binding. Closes #139617 Added: Modified: clang/include/clang/Basic/Attr.td clang/lib/CodeGen/CGHLSLRuntime.cpp clang/lib/Sema/SemaHLSL.cpp clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl clang/test/AST/HLSL/packoffset.hlsl clang/test/AST/HLSL/pch_hlsl_buffer.hlsl clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl clang/test/CodeGenHLSL/cbuffer.hlsl Removed: ################################################################################ diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index dda62fdf03586..a6a7482a94a29 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4790,6 +4790,7 @@ def HLSLResourceBinding: InheritableAttr { RegisterType RegType; std::optional<unsigned> SlotNumber; unsigned SpaceNumber; + std::optional<unsigned> ImplicitBindingOrderID; public: void setBinding(RegisterType RT, std::optional<unsigned> SlotNum, unsigned SpaceNum) { @@ -4811,6 +4812,16 @@ def HLSLResourceBinding: InheritableAttr { unsigned getSpaceNumber() const { return SpaceNumber; } + void setImplicitBindingOrderID(uint32_t Value) { + ImplicitBindingOrderID = Value; + } + bool hasImplicitBindingOrderID() const { + return ImplicitBindingOrderID.has_value(); + } + uint32_t getImplicitBindingOrderID() const { + assert(hasImplicitBindingOrderID() && "attribute does not have implicit binding order id"); + return ImplicitBindingOrderID.value(); + } }]; } diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 5bc71a9b4dd1c..a708b3aea129d 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -23,6 +23,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LLVMContext.h" @@ -42,8 +43,8 @@ using namespace llvm; using llvm::hlsl::CBufferRowSizeInBytes; static void initializeBufferFromBinding(CodeGenModule &CGM, - llvm::GlobalVariable *GV, unsigned Slot, - unsigned Space); + llvm::GlobalVariable *GV, + HLSLResourceBindingAttr *RBA); namespace { @@ -271,13 +272,10 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) { emitBufferGlobalsAndMetadata(BufDecl, BufGV); // Initialize cbuffer from binding (implicit or explicit) - const HLSLResourceBindingAttr *RBA = - BufDecl->getAttr<HLSLResourceBindingAttr>(); - // FIXME: handle implicit binding if no binding attribute is found - // (llvm/llvm-project#110722) - if (RBA && RBA->hasRegisterSlot()) - initializeBufferFromBinding(CGM, BufGV, RBA->getSlotNumber(), - RBA->getSpaceNumber()); + HLSLResourceBindingAttr *RBA = BufDecl->getAttr<HLSLResourceBindingAttr>(); + assert(RBA && + "cbuffer/tbuffer should always have resource binding attribute"); + initializeBufferFromBinding(CGM, BufGV, RBA); } llvm::TargetExtType * @@ -560,19 +558,29 @@ static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV, } static void initializeBufferFromBinding(CodeGenModule &CGM, - llvm::GlobalVariable *GV, unsigned Slot, - unsigned Space) { + llvm::GlobalVariable *GV, + HLSLResourceBindingAttr *RBA) { llvm::Type *Int1Ty = llvm::Type::getInt1Ty(CGM.getLLVMContext()); - llvm::Value *Args[] = { - llvm::ConstantInt::get(CGM.IntTy, Space), /* reg_space */ - llvm::ConstantInt::get(CGM.IntTy, Slot), /* lower_bound */ - llvm::ConstantInt::get(CGM.IntTy, 1), /* range_size */ - llvm::ConstantInt::get(CGM.IntTy, 0), /* index */ - llvm::ConstantInt::get(Int1Ty, false) /* non-uniform */ - }; - initializeBuffer(CGM, GV, - CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic(), - Args); + auto *NonUniform = llvm::ConstantInt::get(Int1Ty, false); + auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0); + auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1); + auto *Space = + llvm::ConstantInt::get(CGM.IntTy, RBA ? RBA->getSpaceNumber() : 0); + + if (RBA->hasRegisterSlot()) { + auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber()); + Intrinsic::ID Intr = + CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic(); + initializeBuffer(CGM, GV, Intr, + {Space, RegSlot, RangeSize, Index, NonUniform}); + } else { + auto *OrderID = + llvm::ConstantInt::get(CGM.IntTy, RBA->getImplicitBindingOrderID()); + Intrinsic::ID Intr = + CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic(); + initializeBuffer(CGM, GV, Intr, + {OrderID, Space, RangeSize, Index, NonUniform}); + } } llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) { diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e6daa67fcee95..c4dcfd3eb8f99 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -537,6 +537,18 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) { BufDecl->addLayoutStruct(LS); } +static void addImplicitBindingAttrToBuffer(Sema &S, HLSLBufferDecl *BufDecl, + uint32_t ImplicitBindingOrderID) { + RegisterType RT = + BufDecl->isCBuffer() ? RegisterType::CBuffer : RegisterType::SRV; + auto *Attr = + HLSLResourceBindingAttr::CreateImplicit(S.getASTContext(), "", "0", {}); + std::optional<unsigned> RegSlot; + Attr->setBinding(RT, RegSlot, 0); + Attr->setImplicitBindingOrderID(ImplicitBindingOrderID); + BufDecl->addAttr(Attr); +} + // Handle end of cbuffer/tbuffer declaration void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) { auto *BufDecl = cast<HLSLBufferDecl>(Dcl); @@ -547,9 +559,17 @@ void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) { // create buffer layout struct createHostLayoutStructForBuffer(SemaRef, BufDecl); - if (std::none_of(Dcl->attr_begin(), Dcl->attr_end(), - [](Attr *A) { return isa<HLSLResourceBindingAttr>(A); })) + HLSLResourceBindingAttr *RBA = Dcl->getAttr<HLSLResourceBindingAttr>(); + if (!RBA || !RBA->hasRegisterSlot()) { SemaRef.Diag(Dcl->getLocation(), diag::warn_hlsl_implicit_binding); + // Use HLSLResourceBindingAttr to transfer implicit binding order_ID + // to codegen. If it does not exist, create an implicit attribute. + uint32_t OrderID = getNextImplicitBindingOrderID(); + if (RBA) + RBA->setImplicitBindingOrderID(OrderID); + else + addImplicitBindingAttrToBuffer(SemaRef, BufDecl, OrderID); + } SemaRef.PopDeclContext(); } @@ -2000,6 +2020,8 @@ void SemaHLSL::ActOnEndOfTranslationUnit(TranslationUnitDecl *TU) { HLSLBufferDecl *DefaultCBuffer = HLSLBufferDecl::CreateDefaultCBuffer( SemaRef.getASTContext(), SemaRef.getCurLexicalContext(), DefaultCBufferDecls); + addImplicitBindingAttrToBuffer(SemaRef, DefaultCBuffer, + getNextImplicitBindingOrderID()); SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer); createHostLayoutStructForBuffer(SemaRef, DefaultCBuffer); diff --git a/clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl b/clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl index 4cca9cc742c07..0cc72fd370633 100644 --- a/clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl +++ b/clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl @@ -21,6 +21,7 @@ cbuffer A { // AST: HLSLBufferDecl {{.*}} line:11:9 cbuffer A // AST-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer +// AST-NEXT: HLSLResourceBindingAttr {{.*}} Implicit "" "0" // AST-NEXT: FullComment // AST-NEXT: ParagraphComment // AST-NEXT: TextComment {{.*}} Text=" CBuffer decl." diff --git a/clang/test/AST/HLSL/packoffset.hlsl b/clang/test/AST/HLSL/packoffset.hlsl index 4fe8aed5cb31a..dc86000a87ee3 100644 --- a/clang/test/AST/HLSL/packoffset.hlsl +++ b/clang/test/AST/HLSL/packoffset.hlsl @@ -5,6 +5,7 @@ cbuffer A { // CHECK-NEXT:-HLSLResourceClassAttr {{.*}} Implicit CBuffer + // CHECK-NEXT: HLSLResourceBindingAttr {{.*}} Implicit "" "0" // CHECK-NEXT: VarDecl {{.*}} A1 'hlsl_constant float4' // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0 float4 A1 : packoffset(c); diff --git a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl index 9c73f587b7210..7fb06f8d3524a 100644 --- a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl +++ b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl @@ -16,12 +16,14 @@ float foo() { // Make sure cbuffer/tbuffer works for PCH. // CHECK: HLSLBufferDecl {{.*}} line:{{[0-9]+}}:9 imported <undeserialized declarations> cbuffer A // CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer +// CHECK-NEXT: HLSLResourceBindingAttr {{.*}} Implicit "" "0" // CHECK-NEXT: VarDecl 0x[[A:[0-9a-f]+]] {{.*}} imported used a 'hlsl_constant float' // CHECK-NEXT: CXXRecordDecl {{.*}} imported implicit <undeserialized declarations> struct __cblayout_A definition // CHECK: FieldDecl {{.*}} imported a 'float' // CHECK: HLSLBufferDecl {{.*}} line:{{[0-9]+}}:9 imported <undeserialized declarations> tbuffer B // CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit SRV +// CHECK-NEXT: HLSLResourceBindingAttr {{.*}} Implicit "" "0" // CHECK-NEXT: VarDecl 0x[[B:[0-9a-f]+]] {{.*}} imported used b 'hlsl_constant float' // CHECK-NEXT: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} imported implicit <undeserialized declarations> struct __cblayout_B definition // CHECK: FieldDecl 0x{{[0-9a-f]+}} {{.*}} imported b 'float' diff --git a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl index c0eb1b138ed04..b36682e065b3a 100644 --- a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl +++ b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl @@ -27,6 +27,7 @@ void main(unsigned GI : SV_GroupIndex) {} // Verify function constructors are emitted // NOINLINE-NEXT: call void @_Z13call_me_firstv() // NOINLINE-NEXT: call void @_Z12then_call_mev() +// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorFunction.hlsl() // NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group() // NOINLINE-NEXT: call void @_Z4mainj(i32 %0) // NOINLINE-NEXT: call void @_Z12call_me_lastv( @@ -36,6 +37,9 @@ void main(unsigned GI : SV_GroupIndex) {} // INLINE-NEXT: alloca // INLINE-NEXT: store i32 12 // INLINE-NEXT: store i32 13 +// INLINE-NEXT: %[[HANDLE:.*]] = call target("dx.CBuffer", target("dx.Layout", %"__cblayout_$Globals", 4, 0)) +// INLINE-NEXT-SAME: @"llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_$Globalss_4_0tt"(i32 0, i32 0, i32 1, i32 0, i1 false) +// INLINE-NEXT: store target("dx.CBuffer", target("dx.Layout", %"__cblayout_$Globals", 4, 0)) %[[HANDLE]], ptr @"$Globals.cb", align 4 // INLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group() // INLINE-NEXT: store i32 % // INLINE-NEXT: store i32 0 diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl index 405f5ef218973..3fb76d57341cf 100644 --- a/clang/test/CodeGenHLSL/cbuffer.hlsl +++ b/clang/test/CodeGenHLSL/cbuffer.hlsl @@ -102,7 +102,7 @@ typedef uint32_t4 uint32_t8[2]; typedef uint4 T1; typedef T1 T2[2]; // check a double typedef -cbuffer CBTypedefArray { +cbuffer CBTypedefArray : register(space2) { uint32_t8 t1[2]; T2 t2[2]; } @@ -268,16 +268,64 @@ cbuffer CB_C { // CHECK: define internal void @_init_buffer_CBScalars.cb() // CHECK-NEXT: entry: -// CHECK-NEXT: %[[HANDLE1:.*]] = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48)) +// CHECK-NEXT: %CBScalars.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48)) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBScalarss_56_0_8_16_24_32_36_40_48tt(i32 5, i32 1, i32 1, i32 0, i1 false) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48)) %CBScalars.cb_h, ptr @CBScalars.cb, align 4 +// CHECK: define internal void @_init_buffer_CBVectors.cb() +// CHECK-NEXT: entry: +// CHECK-NEXT: %CBVectors.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBVectors, 136, 0, 16, 40, 48, 80, 96, 112)) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBVectorss_136_0_16_40_48_80_96_112tt(i32 0, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBVectors, 136, 0, 16, 40, 48, 80, 96, 112)) %CBVectors.cb_h, ptr @CBVectors.cb, align 4 + // CHECK: define internal void @_init_buffer_CBArrays.cb() // CHECK-NEXT: entry: -// CHECK-NEXT: %[[HANDLE2:.*]] = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBArrays, 708, 0, 48, 112, 176, 224, 608, 624, 656)) +// CHECK-NEXT: %CBArrays.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBArrays, 708, 0, 48, 112, 176, 224, 608, 624, 656)) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBArrayss_708_0_48_112_176_224_608_624_656tt(i32 0, i32 2, i32 1, i32 0, i1 false) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBArrays, 708, 0, 48, 112, 176, 224, 608, 624, 656)) %CBArrays.cb_h, ptr @CBArrays.cb, align 4 +// CHECK: define internal void @_init_buffer_CBTypedefArray.cb() +// CHECK-NEXT: entry: +// CHECK-NEXT: %CBTypedefArray.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray, 128, 0, 64)) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBTypedefArrays_128_0_64tt(i32 1, i32 2, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray, 128, 0, 64)) %CBTypedefArray.cb_h, ptr @CBTypedefArray.cb, align 4 + +// CHECK: define internal void @_init_buffer_CBStructs.cb() +// CHECK-NEXT: entry: +// CHECK-NEXT: %CBStructs.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBStructs, 246, 0, 16, 32, 64, 144, 238, 240)) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBStructss_246_0_16_32_64_144_238_240tt(i32 2, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBStructs, 246, 0, 16, 32, 64, 144, 238, 240)) %CBStructs.cb_h, ptr @CBStructs.cb, align 4 + +// CHECK: define internal void @_init_buffer_CBClasses.cb() +// CHECK-NEXT: entry: +// CHECK-NEXT: %CBClasses.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBClasses, 260, 0, 16, 32, 112)) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBClassess_260_0_16_32_112tt(i32 3, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBClasses, 260, 0, 16, 32, 112)) %CBClasses.cb_h, ptr @CBClasses.cb, align 4 + +// CHECK: define internal void @_init_buffer_CBMix.cb() +// CHECK-NEXT: entry: +// CHECK-NEXT: %CBMix.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBMix, 170, 0, 24, 32, 120, 128, 136, 144, 152, 160, 168)) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBMixs_170_0_24_32_120_128_136_144_152_160_168tt(i32 4, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBMix, 170, 0, 24, 32, 120, 128, 136, 144, 152, 160, 168)) %CBMix.cb_h, ptr @CBMix.cb, align 4 + +// CHECK: define internal void @_init_buffer_CB_A.cb() +// CHECK-NEXT: entry: +// CHECK-NEXT: %CB_A.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182)) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_As_188_0_32_76_80_120_128_144_160_182tt(i32 5, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182)) %CB_A.cb_h, ptr @CB_A.cb, align 4 + +// CHECK: define internal void @_init_buffer_CB_B.cb() +// CHECK-NEXT: entry: +// CHECK-NEXT: %CB_B.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88)) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_Bs_94_0_88tt(i32 6, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88)) %CB_B.cb_h, ptr @CB_B.cb, align 4 + +// CHECK: define internal void @_init_buffer_CB_C.cb() +// CHECK-NEXT: entry: +// CHECK-NEXT: %CB_C.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392)) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_Cs_400_0_16_112_128_392tt(i32 7, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392)) %CB_C.cb_h, ptr @CB_C.cb, align 4 + RWBuffer<float> Buf; [numthreads(4,1,1)] @@ -288,7 +336,13 @@ void main() { // CHECK: define internal void @_GLOBAL__sub_I_cbuffer.hlsl() // CHECK-NEXT: entry: // CHECK-NEXT: call void @_init_buffer_CBScalars.cb() +// CHECK-NEXT: call void @_init_buffer_CBVectors.cb() // CHECK-NEXT: call void @_init_buffer_CBArrays.cb() +// CHECK-NEXT: call void @_init_buffer_CBTypedefArray.cb() +// CHECK-NEXT: call void @_init_buffer_CBStructs.cb() +// CHECK-NEXT: call void @_init_buffer_CBClasses.cb() +// CHECK-NEXT: call void @_init_buffer_CBMix.cb() +// CHECK-NEXT: call void @_init_buffer_CB_A.cb() // CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBTYPEDEFARRAY:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBCLASSES:[0-9]+]], // CHECK-SAME: ![[CBMIX:[0-9]+]], ![[CB_A:[0-9]+]], ![[CB_B:[0-9]+]], ![[CB_C:[0-9]+]]} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits