https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/119755
>From 8cebb59304a1f893d94f2a758bc47a62f27c1b8b Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 12 Dec 2024 11:37:46 -0800 Subject: [PATCH 1/4] [HLSL] Codegen for simple `cbuffer` blocks without embedded arrays or structs --- clang/include/clang/Basic/Attr.td | 6 +- clang/lib/CodeGen/CGDeclCXX.cpp | 12 +- clang/lib/CodeGen/CGHLSLRuntime.cpp | 249 +++++++++++------- clang/lib/CodeGen/CGHLSLRuntime.h | 45 +++- clang/lib/Sema/SemaHLSL.cpp | 15 +- .../ByteAddressBuffers-constructors.hlsl | 8 +- .../builtins/RWBuffer-constructor.hlsl | 10 +- .../StructuredBuffers-constructors.hlsl | 8 +- clang/test/CodeGenHLSL/cbuf.hlsl | 26 -- clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl | 23 -- clang/test/CodeGenHLSL/cbuffer.hlsl | 67 +++++ .../CodeGenHLSL/cbuffer_and_namespaces.hlsl | 47 ++++ .../CodeGenHLSL/cbuffer_with_packoffset.hlsl | 33 +++ ...uffer_with_static_global_and_function.hlsl | 28 ++ .../static_global_and_function_in_cb.hlsl | 17 -- 15 files changed, 392 insertions(+), 202 deletions(-) delete mode 100644 clang/test/CodeGenHLSL/cbuf.hlsl delete mode 100644 clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl create mode 100644 clang/test/CodeGenHLSL/cbuffer.hlsl create mode 100644 clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl create mode 100644 clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl create mode 100644 clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl delete mode 100644 clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 90d2a2056fe1ba..f615f45a9524d8 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4711,9 +4711,9 @@ def HLSLPackOffset: HLSLAnnotationAttr { let Args = [IntArgument<"Subcomponent">, IntArgument<"Component">]; let Documentation = [HLSLPackOffsetDocs]; let AdditionalMembers = [{ - unsigned getOffset() { - return subcomponent * 4 + component; - } + unsigned getOffsetInBytes() { + return subcomponent * 16 + component * 4; + } }]; } diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 2c3054605ee754..2869150a5e6648 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -886,6 +886,10 @@ CodeGenModule::EmitCXXGlobalInitFunc() { ModuleInits.push_back(Fn); } + if (getLangOpts().HLSL && getHLSLRuntime().needsResourceBindingInitFn()) { + CXXGlobalInits.push_back(getHLSLRuntime().createResourceBindingInitFn()); + } + if (ModuleInits.empty() && CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty()) return; @@ -1127,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 fb15b1993e74ad..82fae11bc7bc37 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -54,69 +54,110 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) { auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey); DXILValMD->addOperand(Val); } + void addDisableOptimizations(llvm::Module &M) { StringRef Key = "dx.disable_optimizations"; M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1); } -// cbuffer will be translated into global variable in special address space. -// If translate into C, -// cbuffer A { -// float a; -// float b; -// } -// float foo() { return a + b; } -// -// will be translated into -// -// struct A { -// float a; -// float b; -// } cbuffer_A __attribute__((address_space(4))); -// float foo() { return cbuffer_A.a + cbuffer_A.b; } -// -// layoutBuffer will create the struct A type. -// replaceBuffer will replace use of global variable a and b with cbuffer_A.a -// and cbuffer_A.b. -// -void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) { - if (Buf.Constants.empty()) - return; + +// Creates the LLVM struct type representing the shape of the constant buffer +// which will be included in the LLVM target type and calculates the memory +// layout and constant buffer layout offsets of each constant. +static void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) { + assert(!Buf.Constants.empty() && + "empty constant buffer should not be created"); std::vector<llvm::Type *> EltTys; - for (auto &Const : Buf.Constants) { - GlobalVariable *GV = Const.first; - Const.second = EltTys.size(); + unsigned MemOffset = 0, CBufOffset = 0, Size = 0; + + for (auto &C : Buf.Constants) { + GlobalVariable *GV = C.GlobalVar; llvm::Type *Ty = GV->getValueType(); + + assert(!Ty->isArrayTy() && !Ty->isStructTy() && + "arrays and structs in cbuffer are not yet implemened"); + + // scalar type, vector or matrix EltTys.emplace_back(Ty); + unsigned FieldSize = Ty->getScalarSizeInBits() / 8; + if (Ty->isVectorTy()) + FieldSize *= cast<FixedVectorType>(Ty)->getNumElements(); + assert(FieldSize <= 16 && "field side larger than constant buffer row"); + + // set memory layout offset (no padding) + C.MemOffset = MemOffset; + MemOffset += FieldSize; + + // calculate cbuffer layout offset or update total cbuffer size from + // packoffset annotations + if (Buf.HasPackoffset) { + assert(C.CBufferOffset != UINT_MAX && + "cbuffer offset should have been set from packoffset attribute"); + unsigned OffsetAfterField = C.CBufferOffset + FieldSize; + if (Size < OffsetAfterField) + Size = OffsetAfterField; + } else { + // allign to the size of the field + CBufOffset = llvm::alignTo(CBufOffset, FieldSize); + C.CBufferOffset = CBufOffset; + CBufOffset += FieldSize; + Size = CBufOffset; + } } Buf.LayoutStruct = llvm::StructType::get(EltTys[0]->getContext(), EltTys); + Buf.Size = Size; } -GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) { - // Create global variable for CB. - GlobalVariable *CBGV = new GlobalVariable( - Buf.LayoutStruct, /*isConstant*/ true, - GlobalValue::LinkageTypes::ExternalLinkage, nullptr, - llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb." : ".tb."), - GlobalValue::NotThreadLocal); +// Creates LLVM target type target("dx.CBuffer",..) for the constant buffer. +// The target type includes the LLVM struct type representing the shape +// of the constant buffer, size, and a list of offsets for each fields +// in cbuffer layout. +static llvm::Type *getBufferTargetType(LLVMContext &Ctx, + CGHLSLRuntime::Buffer &Buf) { + assert(Buf.LayoutStruct != nullptr && Buf.Size != UINT_MAX && + "the buffer layout has not been calculated yet"); + llvm::SmallVector<unsigned> SizeAndOffsets; + SizeAndOffsets.reserve(Buf.Constants.size() + 1); + SizeAndOffsets.push_back(Buf.Size); + for (CGHLSLRuntime::BufferConstant &C : Buf.Constants) { + SizeAndOffsets.push_back(C.CBufferOffset); + } + return llvm::TargetExtType::get(Ctx, "dx.CBuffer", {Buf.LayoutStruct}, + SizeAndOffsets); +} - 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(); +// Replaces all uses of the temporary constant buffer global variables with +// buffer access intrinsic resource.getpointer. +static void replaceBufferGlobals(CodeGenModule &CGM, + CGHLSLRuntime::Buffer &Buf) { + assert(Buf.IsCBuffer && "tbuffer codegen is not yet supported"); + + GlobalVariable *BufGV = Buf.GlobalVar; + for (auto &Constant : Buf.Constants) { + GlobalVariable *ConstGV = Constant.GlobalVar; + + // TODO: Map to an hlsl_device address space. + llvm::Type *RetTy = ConstGV->getType(); + llvm::Type *TargetTy = BufGV->getValueType(); + + // Replace all uses of GV with CBuffer access + while (ConstGV->use_begin() != ConstGV->use_end()) { + Use &U = *ConstGV->use_begin(); + if (Instruction *UserInstr = dyn_cast<Instruction>(U.getUser())) { + IRBuilder<> Builder(UserInstr); + Value *Handle = Builder.CreateLoad(TargetTy, BufGV); + Value *ResGetPointer = Builder.CreateIntrinsic( + RetTy, Intrinsic::dx_resource_getpointer, + ArrayRef<llvm::Value *>{Handle, + Builder.getInt32(Constant.MemOffset)}); + U.set(ResGetPointer); + } else { + llvm_unreachable("unexpected use of constant value"); + } + } + ConstGV->removeDeadConstantUsers(); + ConstGV->eraseFromParent(); } - return CBGV; } } // namespace @@ -143,6 +184,9 @@ void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) { return; } + assert(!D->getType()->isArrayType() && !D->getType()->isStructureType() && + "codegen for arrays and structs in cbuffer is not yet supported"); + auto *GV = cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(D)); // Add debug info for constVal. if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) @@ -150,13 +194,12 @@ void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) { codegenoptions::DebugInfoKind::LimitedDebugInfo) DI->EmitGlobalVariable(cast<GlobalVariable>(GV), D); - // FIXME: support packoffset. - // See https://github.com/llvm/llvm-project/issues/57914. - uint32_t Offset = 0; - bool HasUserOffset = false; + CB.Constants.emplace_back(GV); - unsigned LowerBound = HasUserOffset ? Offset : UINT_MAX; - CB.Constants.emplace_back(std::make_pair(GV, LowerBound)); + if (HLSLPackOffsetAttr *PO = D->getAttr<HLSLPackOffsetAttr>()) { + CB.HasPackoffset = true; + CB.Constants.back().CBufferOffset = PO->getOffsetInBytes(); + } } void CGHLSLRuntime::addBufferDecls(const DeclContext *DC, Buffer &CB) { @@ -173,9 +216,37 @@ void CGHLSLRuntime::addBufferDecls(const DeclContext *DC, Buffer &CB) { } } +// Creates temporary global variables for all declarations within the constant +// buffer context, calculates the buffer layouts, and then creates a global +// variable for the constant buffer and adds it to the module. +// All uses of the temporary constant globals will be replaced with buffer +// access intrinsic resource.getpointer in CGHLSLRuntime::finishCodeGen. +// Later on in DXILResourceAccess pass these will be transtaled +// to dx.op.cbufferLoadLegacy instructions. void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *D) { - Buffers.emplace_back(Buffer(D)); - addBufferDecls(D, Buffers.back()); + llvm::Module &M = CGM.getModule(); + const DataLayout &DL = M.getDataLayout(); + + assert(D->isCBuffer() && "tbuffer codegen is not supported yet"); + + Buffer &Buf = Buffers.emplace_back(D); + addBufferDecls(D, Buf); + if (Buf.Constants.empty()) { + // empty constant buffer - do not add to globals + Buffers.pop_back(); + return; + } + layoutBuffer(Buf, DL); + + // Create global variable for CB. + llvm::Type *TargetTy = getBufferTargetType(CGM.getLLVMContext(), Buf); + Buf.GlobalVar = new GlobalVariable( + TargetTy, /*isConstant*/ true, GlobalValue::LinkageTypes::ExternalLinkage, + nullptr, llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb" : ".tb"), + GlobalValue::NotThreadLocal); + + M.insertGlobalVariable(Buf.GlobalVar); + ResourcesToBind.emplace_back(Buf.Decl, Buf.GlobalVar); } void CGHLSLRuntime::finishCodeGen() { @@ -189,26 +260,14 @@ void CGHLSLRuntime::finishCodeGen() { if (CGM.getCodeGenOpts().OptimizationLevel == 0) addDisableOptimizations(M); - const DataLayout &DL = M.getDataLayout(); - for (auto &Buf : Buffers) { - layoutBuffer(Buf, DL); - GlobalVariable *GV = replaceBuffer(Buf); - M.insertGlobalVariable(GV); - llvm::hlsl::ResourceClass RC = Buf.IsCBuffer - ? llvm::hlsl::ResourceClass::CBuffer - : llvm::hlsl::ResourceClass::SRV; - llvm::hlsl::ResourceKind RK = Buf.IsCBuffer - ? llvm::hlsl::ResourceKind::CBuffer - : llvm::hlsl::ResourceKind::TBuffer; - addBufferResourceAnnotation(GV, RC, RK, /*IsROV=*/false, - llvm::hlsl::ElementType::Invalid, Buf.Binding); + replaceBufferGlobals(CGM, Buf); } } CGHLSLRuntime::Buffer::Buffer(const HLSLBufferDecl *D) - : Name(D->getName()), IsCBuffer(D->isCBuffer()), - Binding(D->getAttr<HLSLResourceBindingAttr>()) {} + : Name(D->getName()), IsCBuffer(D->isCBuffer()), HasPackoffset(false), + LayoutStruct(nullptr), Decl(D), GlobalVar(nullptr) {} void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV, llvm::hlsl::ResourceClass RC, @@ -237,7 +296,7 @@ void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV, "ResourceMD must have been set by the switch above."); llvm::hlsl::FrontendResource Res( - GV, RK, ET, IsROV, Binding.Reg.value_or(UINT_MAX), Binding.Space); + GV, RK, ET, IsROV, Binding.Slot.value_or(UINT_MAX), Binding.Space); ResourceMD->addOperand(Res.getMetadata()); } @@ -328,12 +387,8 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) { 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(); + Slot = Binding->getSlotNumber(); + Space = Binding->getSpaceNumber(); } else { Space = 0; } @@ -572,24 +627,30 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() { const DataLayout &DL = CGM.getModule().getDataLayout(); Builder.SetInsertPoint(EntryBB); - for (const auto &[VD, GV] : ResourcesToBind) { - for (Attr *A : VD->getAttrs()) { + for (const auto &[Decl, GV] : ResourcesToBind) { + for (Attr *A : Decl->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); + llvm::Type *TargetTy = nullptr; + if (const VarDecl *VD = dyn_cast<VarDecl>(Decl)) { + 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"); + + TargetTy = CGM.getTargetCodeGenInfo().getHLSLType(CGM, AttrResType); + } else { + assert(isa<HLSLBufferDecl>(Decl)); + TargetTy = GV->getValueType(); + } assert(TargetTy != nullptr && "Failed to convert resource handle to target type"); @@ -604,7 +665,7 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() { llvm::Value *CreateHandle = Builder.CreateIntrinsic( /*ReturnType=*/TargetTy, getCreateHandleFromBindingIntrinsic(), Args, - nullptr, Twine(VD->getName()).concat("_h")); + nullptr, Twine(Decl->getName()).concat("_h")); llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index f9efb1bc996412..9c3bbf5bbfe190 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H #define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsDirectX.h" @@ -53,6 +54,7 @@ class StructType; } // namespace llvm namespace clang { +class NamedDecl; class VarDecl; class ParmVarDecl; class HLSLBufferDecl; @@ -112,22 +114,43 @@ class CGHLSLRuntime { //===----------------------------------------------------------------------===// struct BufferResBinding { - // The ID like 2 in register(b2, space1). - std::optional<unsigned> Reg; - // The Space like 1 is register(b2, space1). - // Default value is 0. + // Register slot + std::optional<unsigned> Slot; + // Register space; default value is 0. unsigned Space; + BufferResBinding(HLSLResourceBindingAttr *Attr); }; + + struct BufferConstant { + llvm::GlobalVariable *GlobalVar; + // offset in memory layout (in bytes) + unsigned MemOffset; + // offset in cbuffer layout (in bytes) + unsigned CBufferOffset; + + BufferConstant(llvm::GlobalVariable *GV) + : GlobalVar(GV), MemOffset(UINT_MAX), CBufferOffset(UINT_MAX) {} + }; + struct Buffer { - Buffer(const HLSLBufferDecl *D); llvm::StringRef Name; - // IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer). + // Whether the buffer is a cbuffer (and not a tbuffer). bool IsCBuffer; - BufferResBinding Binding; - // Global variable and offset for each constant. - std::vector<std::pair<llvm::GlobalVariable *, unsigned>> Constants; - llvm::StructType *LayoutStruct = nullptr; + // Whether the buffer has packoffset annotations + bool HasPackoffset; + // List of global constants with memory and cbuffer layout ofsets + std::vector<BufferConstant> Constants; + // LLVM layout type + llvm::StructType *LayoutStruct; + // size of the buffer in cbuffer layout + unsigned Size; + // reference to the AST Decl node with resource binding attribute + const HLSLBufferDecl *Decl; + // global variable for the constant buffer + llvm::GlobalVariable *GlobalVar; + + Buffer(const HLSLBufferDecl *D); }; protected: @@ -169,7 +192,7 @@ class CGHLSLRuntime { llvm::Triple::ArchType getArch(); llvm::SmallVector<Buffer> Buffers; - llvm::SmallVector<std::pair<const VarDecl *, llvm::GlobalVariable *>> + llvm::SmallVector<std::pair<const NamedDecl *, llvm::GlobalVariable *>> ResourcesToBind; }; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 600c800029fd05..9b96806c35f3da 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -164,18 +164,18 @@ Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer, return Result; } -// Calculate the size of a legacy cbuffer type based on +// Calculate the size of a legacy cbuffer type in bytes based on // https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T) { unsigned Size = 0; - constexpr unsigned CBufferAlign = 128; + constexpr unsigned CBufferAlign = 16; if (const RecordType *RT = T->getAs<RecordType>()) { const RecordDecl *RD = RT->getDecl(); for (const FieldDecl *Field : RD->fields()) { QualType Ty = Field->getType(); unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty); - unsigned FieldAlign = 32; + unsigned FieldAlign = 4; if (Ty->isAggregateType()) FieldAlign = CBufferAlign; Size = llvm::alignTo(Size, FieldAlign); @@ -194,7 +194,7 @@ static unsigned calculateLegacyCbufferSize(const ASTContext &Context, calculateLegacyCbufferSize(Context, VT->getElementType()); Size = ElementSize * ElementCount; } else { - Size = Context.getTypeSize(T); + Size = Context.getTypeSize(T) / 8; } return Size; } @@ -229,16 +229,17 @@ void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) { std::sort(PackOffsetVec.begin(), PackOffsetVec.end(), [](const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS, const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) { - return LHS.second->getOffset() < RHS.second->getOffset(); + return LHS.second->getOffsetInBytes() < + RHS.second->getOffsetInBytes(); }); for (unsigned i = 0; i < PackOffsetVec.size() - 1; i++) { VarDecl *Var = PackOffsetVec[i].first; HLSLPackOffsetAttr *Attr = PackOffsetVec[i].second; unsigned Size = calculateLegacyCbufferSize(Context, Var->getType()); - unsigned Begin = Attr->getOffset() * 32; + unsigned Begin = Attr->getOffsetInBytes(); unsigned End = Begin + Size; - unsigned NextBegin = PackOffsetVec[i + 1].second->getOffset() * 32; + unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes(); if (End > NextBegin) { VarDecl *NextVar = PackOffsetVec[i + 1].first; Diag(NextVar->getLocation(), diag::err_hlsl_packoffset_overlap) diff --git a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl index 45e135427ba9c3..f1e949ab652cce 100644 --- a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl @@ -15,10 +15,6 @@ 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 @_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.handle.fromBinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false) @@ -27,3 +23,7 @@ RasterizerOrderedByteAddressBuffer Buffer2: register(u3, space4); // 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.handle.fromBinding.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: define internal void @_GLOBAL__sub_I_ByteAddressBuffers_constructors.hlsl() +// CHECK: entry: +// CHECK: call void @_init_resource_bindings() diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl index c2db56e2b2bddf..8f252ea357459a 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl @@ -12,14 +12,14 @@ RWBuffer<float> Buf : register(u5, space3); // 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.handle.fromBinding.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.handle.fromBinding.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: 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() diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl index d84e92242ffb4d..17cba38cc8283f 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl @@ -31,10 +31,6 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2); // CHECK: define linkonce_odr void @_ZN4hlsl33RasterizerOrderedStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) // 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.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) @@ -58,3 +54,7 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2); // 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.handle.fromBinding.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: define internal void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl() +// CHECK: entry: +// CHECK: call void @_init_resource_bindings() diff --git a/clang/test/CodeGenHLSL/cbuf.hlsl b/clang/test/CodeGenHLSL/cbuf.hlsl deleted file mode 100644 index 3f9d4514967dd2..00000000000000 --- a/clang/test/CodeGenHLSL/cbuf.hlsl +++ /dev/null @@ -1,26 +0,0 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s - -// CHECK: @[[CB:.+]] = external constant { float, double } -cbuffer A : register(b0, space2) { - float a; - double b; -} - -// CHECK: @[[TB:.+]] = external constant { float, double } -tbuffer A : register(t2, space1) { - float c; - double d; -} - -float foo() { -// CHECK: load float, ptr @[[CB]], align 4 -// CHECK: load double, ptr getelementptr ({ float, double }, ptr @[[CB]], i32 0, i32 1), align 8 -// CHECK: load float, ptr @[[TB]], align 4 -// CHECK: load double, ptr getelementptr ({ float, double }, ptr @[[TB]], i32 0, i32 1), align 8 - return a + b + c*d; -} - -// CHECK: !hlsl.cbufs = !{![[CBMD:[0-9]+]]} -// CHECK: ![[CBMD]] = !{ptr @[[CB]], i32 13, i32 0, i1 false, i32 0, i32 2} diff --git a/clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl b/clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl deleted file mode 100644 index 73dc376942dfb7..00000000000000 --- a/clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s - -// Make sure cbuffer inside namespace works. -// CHECK: @[[CB:.+]] = external constant { float } -// CHECK: @[[TB:.+]] = external constant { float } -namespace n0 { -namespace n1 { - cbuffer A { - float a; - } -} - tbuffer B { - float b; - } -} - -float foo() { -// CHECK: load float, ptr @[[CB]], align 4 -// CHECK: load float, ptr @[[TB]], align 4 - return n0::n1::a + n0::b; -} diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl new file mode 100644 index 00000000000000..4d6b55157f30a5 --- /dev/null +++ b/clang/test/CodeGenHLSL/cbuffer.hlsl @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-compute %s \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: @CB1.cb = external constant target("dx.CBuffer", { float, double }, 16, 0, 8) +cbuffer CB1 : register(b0, space2) { + float a; + double b; +} + +// CHECK: @ParticleLifeCB.cb = external constant target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) +cbuffer ParticleLifeCB : register(b2, space1) { + uint ParticleTypeMax; + uint NumParticles; + float2 WorldSize; + float Friction; + float ForceMultipler; +} + +float foo() { +// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float, double }, 16, 0, 8), ptr @CB1.cb, align 4 +// CHECK: %[[PTR1:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_16_0_8t(target("dx.CBuffer", { float, double }, 16, 0, 8) %[[HANDLE1]], i32 0) +// CHECK: load float, ptr %[[PTR1]], align 4 + +// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float, double }, 16, 0, 8), ptr @CB1.cb, align 4 +// CHECK: %[[PTR2:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_16_0_8t(target("dx.CBuffer", { float, double }, 16, 0, 8) %[[HANDLE2]], i32 4) +// CHECK: load double, ptr %[[PTR2]], align 8 + +// CHECK: %[[HANDLE3:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4 +// CHECK: %[[PTR3:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t( +// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) %[[HANDLE3]], i32 0) +// CHECK: load i32, ptr %[[PTR3]], align 4 + +// CHECK: %[[HANDLE4:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4 +// CHECK: %[[PTR4:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t( +// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) %[[HANDLE4]], i32 8) +// CHECK: load <2 x float>, ptr %[[PTR4]], align 8 + +// CHECK: %[[HANDLE5:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4 +// CHECK: %[[PTR5:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t( +// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) %[[HANDLE5]], i32 20) +// CHECK: load float, ptr %[[PTR5]], align 4 + return a + b + ParticleTypeMax + WorldSize.y * ForceMultipler; +} + +// CHECK: define void @main() +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @_GLOBAL__sub_I_cbuffer.hlsl() +// CHECK-NEXT: call void @_Z4mainv() +// CHECK-NEXT: ret void + +// CHECK: define internal void @_init_resource_bindings() { +// CHECK-NEXT: entry: +// CHECK-NEXT: %CB1_h = call target("dx.CBuffer", { float, double }, 16, 0, 8) +// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_sl_f32f64s_16_0_8t(i32 2, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", { float, double }, 16, 0, 8) %CB1_h, ptr @CB1.cb, align 4 +// CHECK-NEXT: %ParticleLifeCB_h = call target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) +// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t(i32 1, i32 2, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) %ParticleLifeCB_h, ptr @ParticleLifeCB.cb, align 4 + +// CHECK: define internal void @_GLOBAL__sub_I_cbuffer.hlsl() +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @_init_resource_bindings() +// CHECK-NEXT: ret void + +[numthreads(4,1,1)] +void main() {} diff --git a/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl b/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl new file mode 100644 index 00000000000000..860716ad3e582a --- /dev/null +++ b/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// Make sure cbuffer inside namespace works. +// CHECK: @A.cb = external constant target("dx.CBuffer", { float }, 4, 0) +// CHECK: @B.cb = external constant target("dx.CBuffer", { float }, 4, 0) +// CHECK: @C.cb = external constant target("dx.CBuffer", { float }, 4, 0) + +namespace n0 { + namespace n1 { + cbuffer A { + float a; + } + } + cbuffer B { + float a; + } + namespace n2 { + cbuffer C { + float a; + } + } +} + +float foo() { +// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr @A.cb, align 4 +// CHECK: %[[PTR1:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { float }, 4, 0) %[[HANDLE1]], i32 0) +// CHECK: %[[VAL1:[0-9]+]] = load float, ptr %[[PTR1]], align 4 + +// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr @B.cb, align 4 +// CHECK: %[[PTR2:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { float }, 4, 0) %[[HANDLE2]], i32 0) +// CHECK: %[[VAL2:[0-9]+]] = load float, ptr %[[PTR2]], align 4 + +// CHECK: %add = fadd float %[[VAL1]], %[[VAL2]] + +// CHECK: %[[HANDLE3:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr @C.cb, align 4 +// CHECK: %[[PTR3:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { float }, 4, 0) %[[HANDLE3]], i32 0) +// CHECK: %[[VAL3:[0-9]+]] = load float, ptr %[[PTR3]], align 4 + +// CHECK: %add1 = fadd float %add, %[[VAL3]] + + return n0::n1::a + n0::a + n0::n2::a; +} + +[numthreads(4,1,1)] +void main() {} diff --git a/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl b/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl new file mode 100644 index 00000000000000..58891659179aed --- /dev/null +++ b/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-compute %s \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: @CB.cb = external constant target("dx.CBuffer", { float, double }, 176, 16, 168) +cbuffer CB : register(b1, space3) { + float a : packoffset(c1.x); + double b : packoffset(c10.z); +} + +float foo() { +// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float, double }, 176, 16, 168), ptr @CB.cb, align 4 +// CHECK: %[[PTR1:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_176_16_168t( +// CHECK-SAME: target("dx.CBuffer", { float, double }, 176, 16, 168) %[[HANDLE1]], i32 0) +// CHECK: load float, ptr %[[PTR1]], align 4 + +// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float, double }, 176, 16, 168), ptr @CB.cb, align 4 +// CHECK: %[[PTR2:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_176_16_168t( +// CHECK-SAME: target("dx.CBuffer", { float, double }, 176, 16, 168) %[[HANDLE2]], i32 4) +// CHECK: load double, ptr %[[PTR2]], align 8 + return a + b; +} + +// CHECK: define internal void @_init_resource_bindings() { +// CHECK-NEXT: entry: +// CHECK-NEXT: %CB_h = call target("dx.CBuffer", { float, double }, 176, 16, 168) +// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_sl_f32f64s_176_16_168t(i32 3, i32 1, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", { float, double }, 176, 16, 168) %CB_h, ptr @CB.cb, align 4 + +[numthreads(4,1,1)] +void main() { + foo(); +} diff --git a/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl b/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl new file mode 100644 index 00000000000000..c72eac85ca675e --- /dev/null +++ b/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-DAG: @_ZL1b = internal global float 3.000000e+00, align 4 +// CHECK-DAG: @A.cb = external constant target("dx.CBuffer", { float }, 4, 0) +// CHECK-NOT: @B.cb + +cbuffer A { + float a; + static float b = 3; + float foo() { return a + b; } +} + +cbuffer B { + // intentionally empty +} + + +// CHECK: define noundef float @_Z3foov() #0 { +// CHECK: %[[HANDLE:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr @A.cb, align 4 +// CHECK: %[[PTR:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { float }, 4, 0) %[[HANDLE]], i32 0) +// CHECK: %[[VAL1:[0-9]+]] = load float, ptr %[[PTR]], align 4 +// CHECK: %[[VAL2:[0-9]+]] = load float, ptr @_ZL1b, align 4 +// CHECK: %add = fadd float %[[VAL1]], %[[VAL2]] + +extern float bar() { + return foo(); +} diff --git a/clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl b/clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl deleted file mode 100644 index f85bab2113170b..00000000000000 --- a/clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library %s \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s - -// CHECK-DAG: @[[CB:.+]] = external constant { float } - -cbuffer A { - float a; - // CHECK-DAG:@_ZL1b = internal global float 3.000000e+00, align 4 - static float b = 3; - // CHECK:load float, ptr @[[CB]], align 4 - // CHECK:load float, ptr @_ZL1b, align 4 - float foo() { return a + b; } -} - -float bar() { - return foo(); -} >From dee03ca52a009b3e71fe2c976aa59473a8d970cf Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 12 Dec 2024 12:35:48 -0800 Subject: [PATCH 2/4] couple of commas to improve readability --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 82fae11bc7bc37..cfa77ccd1054d6 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -60,8 +60,8 @@ void addDisableOptimizations(llvm::Module &M) { M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1); } -// Creates the LLVM struct type representing the shape of the constant buffer -// which will be included in the LLVM target type and calculates the memory +// Creates the LLVM struct type representing the shape of the constant buffer, +// which will be included in the LLVM target type, and calculates the memory // layout and constant buffer layout offsets of each constant. static void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) { assert(!Buf.Constants.empty() && >From 7274d067aa82e178558521576df21041686b97c1 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 19 Dec 2024 14:29:53 -0800 Subject: [PATCH 3/4] Move target type and cbuffer layout calculations to DirectXTargetInfo --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 159 ++++++++---------- clang/lib/CodeGen/CGHLSLRuntime.h | 37 ++-- clang/lib/CodeGen/TargetInfo.h | 5 +- clang/lib/CodeGen/Targets/DirectX.cpp | 127 +++++++++++++- clang/lib/CodeGen/Targets/SPIR.cpp | 9 +- clang/test/CodeGenHLSL/cbuffer.hlsl | 64 +++---- .../CodeGenHLSL/cbuffer_and_namespaces.hlsl | 32 ++-- .../CodeGenHLSL/cbuffer_with_packoffset.hlsl | 25 +-- ...uffer_with_static_global_and_function.hlsl | 11 +- 9 files changed, 289 insertions(+), 180 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index cfa77ccd1054d6..0c8a11c6885815 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -16,6 +16,7 @@ #include "CGDebugInfo.h" #include "CodeGenModule.h" #include "TargetInfo.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/Basic/TargetOptions.h" #include "llvm/IR/GlobalVariable.h" @@ -29,7 +30,6 @@ using namespace clang; using namespace CodeGen; -using namespace clang::hlsl; using namespace llvm; namespace { @@ -60,97 +60,83 @@ void addDisableOptimizations(llvm::Module &M) { M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1); } -// Creates the LLVM struct type representing the shape of the constant buffer, -// which will be included in the LLVM target type, and calculates the memory -// layout and constant buffer layout offsets of each constant. -static void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) { - assert(!Buf.Constants.empty() && - "empty constant buffer should not be created"); - - std::vector<llvm::Type *> EltTys; - unsigned MemOffset = 0, CBufOffset = 0, Size = 0; - - for (auto &C : Buf.Constants) { - GlobalVariable *GV = C.GlobalVar; - llvm::Type *Ty = GV->getValueType(); - - assert(!Ty->isArrayTy() && !Ty->isStructTy() && - "arrays and structs in cbuffer are not yet implemened"); - - // scalar type, vector or matrix - EltTys.emplace_back(Ty); - unsigned FieldSize = Ty->getScalarSizeInBits() / 8; - if (Ty->isVectorTy()) - FieldSize *= cast<FixedVectorType>(Ty)->getNumElements(); - assert(FieldSize <= 16 && "field side larger than constant buffer row"); - - // set memory layout offset (no padding) - C.MemOffset = MemOffset; - MemOffset += FieldSize; - - // calculate cbuffer layout offset or update total cbuffer size from - // packoffset annotations - if (Buf.HasPackoffset) { - assert(C.CBufferOffset != UINT_MAX && - "cbuffer offset should have been set from packoffset attribute"); - unsigned OffsetAfterField = C.CBufferOffset + FieldSize; - if (Size < OffsetAfterField) - Size = OffsetAfterField; - } else { - // allign to the size of the field - CBufOffset = llvm::alignTo(CBufOffset, FieldSize); - C.CBufferOffset = CBufOffset; - CBufOffset += FieldSize; - Size = CBufOffset; - } - } - Buf.LayoutStruct = llvm::StructType::get(EltTys[0]->getContext(), EltTys); - Buf.Size = Size; -} - -// Creates LLVM target type target("dx.CBuffer",..) for the constant buffer. -// The target type includes the LLVM struct type representing the shape -// of the constant buffer, size, and a list of offsets for each fields -// in cbuffer layout. -static llvm::Type *getBufferTargetType(LLVMContext &Ctx, - CGHLSLRuntime::Buffer &Buf) { - assert(Buf.LayoutStruct != nullptr && Buf.Size != UINT_MAX && - "the buffer layout has not been calculated yet"); - llvm::SmallVector<unsigned> SizeAndOffsets; - SizeAndOffsets.reserve(Buf.Constants.size() + 1); - SizeAndOffsets.push_back(Buf.Size); - for (CGHLSLRuntime::BufferConstant &C : Buf.Constants) { - SizeAndOffsets.push_back(C.CBufferOffset); +// Creates resource handle representing the constant buffer. +// For cbuffer declaration: +// +// cbuffer MyConstants { +// float a; +// } +// +// creates a structure type MyConstants and then returns the resource handle +// that would be spelled as: +// +// __hlsl_resource_t [[hlsl::resource_class(CBuffer)]] +// [[contained_type(MyConstants)]] +// +static const clang::Type *getBufferHandleType(CGHLSLRuntime::Buffer &Buf) { + HLSLBufferDecl *BD = Buf.Decl; + ASTContext &AST = BD->getASTContext(); + + // create struct type for the constant buffer; filter out any declarations + // that are not a VarDecls or that are static + CXXRecordDecl *StructDecl = CXXRecordDecl::Create( + BD->getASTContext(), TagDecl::TagKind::Class, BD->getDeclContext(), + BD->getLocation(), BD->getLocation(), BD->getIdentifier()); + StructDecl->startDefinition(); + for (Decl *it : Buf.Decl->decls()) { + const VarDecl *VD = dyn_cast<VarDecl>(it); + if (!VD || VD->getStorageClass() == SC_Static) + continue; + auto *Field = FieldDecl::Create( + AST, StructDecl, VD->getLocation(), VD->getLocation(), + VD->getIdentifier(), VD->getType(), VD->getTypeSourceInfo(), nullptr, + false, InClassInitStyle::ICIS_NoInit); + Field->setAccess(AccessSpecifier::AS_private); + StructDecl->addDecl(Field); } - return llvm::TargetExtType::get(Ctx, "dx.CBuffer", {Buf.LayoutStruct}, - SizeAndOffsets); + StructDecl->completeDefinition(); + assert(!StructDecl->fields().empty() && "empty cbuffer should not get here"); + + // create the resource handle type + HLSLAttributedResourceType::Attributes ResAttrs(dxil::ResourceClass::CBuffer, + false, false); + QualType ContainedTy = QualType(StructDecl->getTypeForDecl(), 0); + return AST + .getHLSLAttributedResourceType(AST.HLSLResourceTy, ContainedTy, ResAttrs) + .getTypePtr(); } // Replaces all uses of the temporary constant buffer global variables with -// buffer access intrinsic resource.getpointer. +// buffer access intrinsic resource.getpointer and GEP. static void replaceBufferGlobals(CodeGenModule &CGM, CGHLSLRuntime::Buffer &Buf) { assert(Buf.IsCBuffer && "tbuffer codegen is not yet supported"); GlobalVariable *BufGV = Buf.GlobalVar; - for (auto &Constant : Buf.Constants) { - GlobalVariable *ConstGV = Constant.GlobalVar; + llvm::Type *TargetTy = BufGV->getValueType(); + llvm::Type *BufStructTy = cast<TargetExtType>(TargetTy)->getTypeParameter(0); + unsigned Index = 0; + for (auto ConstIt = Buf.Constants.begin(); ConstIt != Buf.Constants.end(); + ++ConstIt, ++Index) { + GlobalVariable *ConstGV = *ConstIt; // TODO: Map to an hlsl_device address space. llvm::Type *RetTy = ConstGV->getType(); - llvm::Type *TargetTy = BufGV->getValueType(); // Replace all uses of GV with CBuffer access while (ConstGV->use_begin() != ConstGV->use_end()) { Use &U = *ConstGV->use_begin(); if (Instruction *UserInstr = dyn_cast<Instruction>(U.getUser())) { IRBuilder<> Builder(UserInstr); + Value *Zero = Builder.getInt32(0); Value *Handle = Builder.CreateLoad(TargetTy, BufGV); - Value *ResGetPointer = Builder.CreateIntrinsic( - RetTy, Intrinsic::dx_resource_getpointer, - ArrayRef<llvm::Value *>{Handle, - Builder.getInt32(Constant.MemOffset)}); - U.set(ResGetPointer); + Value *ResGetPointer = + Builder.CreateIntrinsic(RetTy, Intrinsic::dx_resource_getpointer, + ArrayRef<llvm::Value *>{Handle, Zero}); + Value *GEP = Builder.CreateGEP(BufStructTy, ResGetPointer, + {Zero, Builder.getInt32(Index)}, + ConstGV->getName()); + U.set(GEP); } else { llvm_unreachable("unexpected use of constant value"); } @@ -162,11 +148,14 @@ static void replaceBufferGlobals(CodeGenModule &CGM, } // namespace -llvm::Type *CGHLSLRuntime::convertHLSLSpecificType(const Type *T) { +llvm::Type * +CGHLSLRuntime::convertHLSLSpecificType(const Type *T, + const HLSLBufferDecl *BufferDecl) { assert(T->isHLSLSpecificType() && "Not an HLSL specific type!"); // Check if the target has a specific translation for this type first. - if (llvm::Type *TargetTy = CGM.getTargetCodeGenInfo().getHLSLType(CGM, T)) + if (llvm::Type *TargetTy = + CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, BufferDecl)) return TargetTy; llvm_unreachable("Generic handling of HLSL types is not supported."); @@ -196,10 +185,8 @@ void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) { CB.Constants.emplace_back(GV); - if (HLSLPackOffsetAttr *PO = D->getAttr<HLSLPackOffsetAttr>()) { + if (HLSLPackOffsetAttr *PO = D->getAttr<HLSLPackOffsetAttr>()) CB.HasPackoffset = true; - CB.Constants.back().CBufferOffset = PO->getOffsetInBytes(); - } } void CGHLSLRuntime::addBufferDecls(const DeclContext *DC, Buffer &CB) { @@ -217,15 +204,14 @@ void CGHLSLRuntime::addBufferDecls(const DeclContext *DC, Buffer &CB) { } // Creates temporary global variables for all declarations within the constant -// buffer context, calculates the buffer layouts, and then creates a global -// variable for the constant buffer and adds it to the module. +// buffer context, creates a global variable for the constant buffer and adds +// it to the module. // All uses of the temporary constant globals will be replaced with buffer // access intrinsic resource.getpointer in CGHLSLRuntime::finishCodeGen. // Later on in DXILResourceAccess pass these will be transtaled // to dx.op.cbufferLoadLegacy instructions. -void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *D) { +void CGHLSLRuntime::addBuffer(HLSLBufferDecl *D) { llvm::Module &M = CGM.getModule(); - const DataLayout &DL = M.getDataLayout(); assert(D->isCBuffer() && "tbuffer codegen is not supported yet"); @@ -236,10 +222,9 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *D) { Buffers.pop_back(); return; } - layoutBuffer(Buf, DL); - // Create global variable for CB. - llvm::Type *TargetTy = getBufferTargetType(CGM.getLLVMContext(), Buf); + llvm::Type *TargetTy = convertHLSLSpecificType( + getBufferHandleType(Buf), Buf.HasPackoffset ? Buf.Decl : nullptr); Buf.GlobalVar = new GlobalVariable( TargetTy, /*isConstant*/ true, GlobalValue::LinkageTypes::ExternalLinkage, nullptr, llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb" : ".tb"), @@ -265,9 +250,9 @@ void CGHLSLRuntime::finishCodeGen() { } } -CGHLSLRuntime::Buffer::Buffer(const HLSLBufferDecl *D) +CGHLSLRuntime::Buffer::Buffer(HLSLBufferDecl *D) : Name(D->getName()), IsCBuffer(D->isCBuffer()), HasPackoffset(false), - LayoutStruct(nullptr), Decl(D), GlobalVar(nullptr) {} + Decl(D), GlobalVar(nullptr) {} void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV, llvm::hlsl::ResourceClass RC, diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 9c3bbf5bbfe190..6e5d26a93b253b 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -18,15 +18,13 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/IR/IntrinsicsDirectX.h" -#include "llvm/IR/IntrinsicsSPIRV.h" - -#include "clang/Basic/Builtins.h" -#include "clang/Basic/HLSLRuntime.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Frontend/HLSL/HLSLResource.h" +#include "llvm/IR/IntrinsicsDirectX.h" +#include "llvm/IR/IntrinsicsSPIRV.h" +#include "llvm/TargetParser/Triple.h" #include <optional> #include <vector> @@ -122,35 +120,20 @@ class CGHLSLRuntime { BufferResBinding(HLSLResourceBindingAttr *Attr); }; - struct BufferConstant { - llvm::GlobalVariable *GlobalVar; - // offset in memory layout (in bytes) - unsigned MemOffset; - // offset in cbuffer layout (in bytes) - unsigned CBufferOffset; - - BufferConstant(llvm::GlobalVariable *GV) - : GlobalVar(GV), MemOffset(UINT_MAX), CBufferOffset(UINT_MAX) {} - }; - struct Buffer { llvm::StringRef Name; // Whether the buffer is a cbuffer (and not a tbuffer). bool IsCBuffer; // Whether the buffer has packoffset annotations bool HasPackoffset; - // List of global constants with memory and cbuffer layout ofsets - std::vector<BufferConstant> Constants; - // LLVM layout type - llvm::StructType *LayoutStruct; - // size of the buffer in cbuffer layout - unsigned Size; + // List of global constants + std::vector<llvm::GlobalVariable *> Constants; // reference to the AST Decl node with resource binding attribute - const HLSLBufferDecl *Decl; + HLSLBufferDecl *Decl; // global variable for the constant buffer llvm::GlobalVariable *GlobalVar; - Buffer(const HLSLBufferDecl *D); + Buffer(HLSLBufferDecl *D); }; protected: @@ -163,12 +146,14 @@ class CGHLSLRuntime { CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {} virtual ~CGHLSLRuntime() {} - llvm::Type *convertHLSLSpecificType(const Type *T); + llvm::Type * + convertHLSLSpecificType(const Type *T, + const HLSLBufferDecl *BufferDecl = nullptr); void annotateHLSLResource(const VarDecl *D, llvm::GlobalVariable *GV); void generateGlobalCtorDtorCalls(); - void addBuffer(const HLSLBufferDecl *D); + void addBuffer(HLSLBufferDecl *D); void finishCodeGen(); void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn); diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index ab3142bdea684e..28c511249c1630 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -33,6 +33,7 @@ class Value; namespace clang { class Decl; +class HLSLBufferDecl; namespace CodeGen { class ABIInfo; @@ -439,7 +440,9 @@ class TargetCodeGenInfo { } /// Return an LLVM type that corresponds to a HLSL type - virtual llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *T) const { + virtual llvm::Type * + getHLSLType(CodeGenModule &CGM, const Type *T, + const HLSLBufferDecl *BufDecl = nullptr) const { return nullptr; } diff --git a/clang/lib/CodeGen/Targets/DirectX.cpp b/clang/lib/CodeGen/Targets/DirectX.cpp index 7935f7ae370047..e5d36cd0ba3478 100644 --- a/clang/lib/CodeGen/Targets/DirectX.cpp +++ b/clang/lib/CodeGen/Targets/DirectX.cpp @@ -8,6 +8,8 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" +#include "clang/AST/Attrs.inc" +#include "clang/AST/Decl.h" #include "llvm/IR/DerivedTypes.h" using namespace clang; @@ -24,11 +26,116 @@ class DirectXTargetCodeGenInfo : public TargetCodeGenInfo { DirectXTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {} - llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *T) const override; + llvm::Type * + getHLSLType(CodeGenModule &CGM, const Type *T, + const HLSLBufferDecl *BufDecl = nullptr) const override; }; -llvm::Type *DirectXTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM, - const Type *Ty) const { +static bool hasPackoffset(const HLSLBufferDecl *BufferDecl) { + // If one valid constant buffer declaration has a packoffset annotation + // then they all need to have them. + for (auto *D : BufferDecl->decls()) + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + if (VD->getStorageClass() != SC_Static) + return VD->hasAttr<HLSLPackOffsetAttr>(); + return false; +} + +// Fills in the Layout based on the constant buffer packoffset annotations +// found in the HLSLBufferDecl instance. +// The first item in the Layout vector will be set to the size of the buffer, +// which is the highest packoffset value + size of its field. +// After the size there will be a list of offsets (in bytes) for each field. +// This layout encoding will be used in the LLVM target type +// for constant buffers target("dx.CBuffer",..). +static void createConstantBufferLayoutFromPackoffset( + CodeGenModule &CGM, llvm::Type *BufferTy, SmallVector<unsigned> &Layout, + const HLSLBufferDecl *BufferDecl) { + assert(BufferDecl && hasPackoffset(BufferDecl) && + "expected non-null buffer declaration with packoffset attributes on " + "its fields"); + assert(isa<llvm::StructType>(BufferTy) && "expected struct"); + + // total buffer size - equals to the highest packoffset value plus the size of + // its element + unsigned Size = 0; + // reserve the first spot in the layout vector for the buffer size + Layout.push_back(UINT_MAX); + + auto DeclIt = BufferDecl->decls_begin(); + for (llvm::Type *Ty : cast<llvm::StructType>(BufferTy)->elements()) { + assert(!Ty->isArrayTy() && !Ty->isStructTy() && + "arrays and structs in cbuffer are not yet implemened"); + + VarDecl *VD = nullptr; + // ignore any declaration that is not var decls or that is static + while (DeclIt != BufferDecl->decls_end()) { + VD = llvm::dyn_cast<VarDecl>(*DeclIt); + DeclIt++; + if (VD && VD->getStorageClass() != SC_Static) + break; + } + assert(VD && "number of declaration in constant buffer does not match " + "number of element in buffer struct"); + assert(CGM.getTypes().ConvertType(VD->getType()) == Ty && + "constant types do not match"); + + HLSLPackOffsetAttr *POAttr = VD->getAttr<HLSLPackOffsetAttr>(); + assert(POAttr && "expected packoffset attribute on every declaration"); + + unsigned Offset = POAttr->getOffsetInBytes(); + Layout.push_back(Offset); + + unsigned FieldSize = Ty->getScalarSizeInBits() / 8; + if (Offset + FieldSize > Size) + Size = Offset + FieldSize; + } + Layout[0] = Size; +} + +// Calculated constant buffer layout. The first item in the Layout +// vector will be set to the size of the buffer followed by the offsets +// (in bytes) for each field. +// This layout encoding will be used in the LLVM target type +// for constant buffers target("dx.CBuffer",..). +static void +calculateConstantBufferLayout(CodeGenModule &CGM, llvm::Type *BufferTy, + SmallVector<unsigned> &Layout, + const HLSLBufferDecl *BufferDecl = nullptr) { + assert(isa<llvm::StructType>(BufferTy) && "expected struct"); + assert(BufferTy->getStructNumElements() != 0 && + "empty constant buffer should not be created"); + + if (BufferDecl && hasPackoffset(BufferDecl)) { + createConstantBufferLayoutFromPackoffset(CGM, BufferTy, Layout, BufferDecl); + return; + } + + unsigned CBufOffset = 0, Size = 0; + Layout.push_back(UINT_MAX); // reserve first spot for the buffer size + + for (const llvm::Type *ElTy : cast<llvm::StructType>(BufferTy)->elements()) { + assert(!ElTy->isArrayTy() && !ElTy->isStructTy() && + "arrays and structs in cbuffer are not yet implemened"); + + // scalar type, vector or matrix + unsigned FieldSize = ElTy->getScalarSizeInBits() / 8; + if (ElTy->isVectorTy()) + FieldSize *= cast<llvm::FixedVectorType>(ElTy)->getNumElements(); + assert(FieldSize <= 16 && "field side larger than constant buffer row"); + + // align to the size of the field + CBufOffset = llvm::alignTo(CBufOffset, FieldSize); + Layout.push_back(CBufOffset); + CBufOffset += FieldSize; + Size = CBufOffset; + } + Layout[0] = Size; +} + +llvm::Type * +DirectXTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM, const Type *Ty, + const HLSLBufferDecl *BufDecl) const { auto *ResType = dyn_cast<HLSLAttributedResourceType>(Ty); if (!ResType) return nullptr; @@ -56,9 +163,17 @@ llvm::Type *DirectXTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM, return llvm::TargetExtType::get(Ctx, TypeName, {ElemType}, Ints); } - case llvm::dxil::ResourceClass::CBuffer: - llvm_unreachable("dx.CBuffer handles are not implemented yet"); - break; + case llvm::dxil::ResourceClass::CBuffer: { + QualType StructTy = ResType->getContainedType(); + if (StructTy.isNull()) + return nullptr; + + llvm::Type *Ty = CGM.getTypes().ConvertType(StructTy); + + SmallVector<unsigned> BufferLayout; + calculateConstantBufferLayout(CGM, Ty, BufferLayout, BufDecl); + return llvm::TargetExtType::get(Ctx, "dx.CBuffer", {Ty}, BufferLayout); + } case llvm::dxil::ResourceClass::Sampler: llvm_unreachable("dx.Sampler handles are not implemented yet"); break; diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index a48fe9d5f1ee9c..d3b0e8874b56ad 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -52,7 +52,9 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo { unsigned getOpenCLKernelCallingConv() const override; llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override; - llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *Ty) const override; + llvm::Type * + getHLSLType(CodeGenModule &CGM, const Type *T, + const HLSLBufferDecl *BufDecl = nullptr) const override; llvm::Type *getSPIRVImageTypeFromHLSLResource( const HLSLAttributedResourceType::Attributes &attributes, llvm::Type *ElementType, llvm::LLVMContext &Ctx) const; @@ -327,8 +329,9 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM, return nullptr; } -llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM, - const Type *Ty) const { +llvm::Type * +CommonSPIRTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM, const Type *Ty, + const HLSLBufferDecl *BufDecl) const { auto *ResType = dyn_cast<HLSLAttributedResourceType>(Ty); if (!ResType) return nullptr; diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl index 4d6b55157f30a5..77d408c9251cc3 100644 --- a/clang/test/CodeGenHLSL/cbuffer.hlsl +++ b/clang/test/CodeGenHLSL/cbuffer.hlsl @@ -2,14 +2,17 @@ // RUN: dxil-pc-shadermodel6.3-compute %s \ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s -// CHECK: @CB1.cb = external constant target("dx.CBuffer", { float, double }, 16, 0, 8) -cbuffer CB1 : register(b0, space2) { +// CHECK: %class.CB = type { float, double } +// CHECK: %class.ParticleLife = type { i32, i32, <2 x float>, float, float } + +// CHECK: @CB.cb = external constant target("dx.CBuffer", %class.CB, 16, 0, 8) +cbuffer CB : register(b0, space2) { float a; double b; } -// CHECK: @ParticleLifeCB.cb = external constant target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) -cbuffer ParticleLifeCB : register(b2, space1) { +// CHECK: @ParticleLife.cb = external constant target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20) +cbuffer ParticleLife : register(b2, space1) { uint ParticleTypeMax; uint NumParticles; float2 WorldSize; @@ -18,28 +21,31 @@ cbuffer ParticleLifeCB : register(b2, space1) { } float foo() { -// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float, double }, 16, 0, 8), ptr @CB1.cb, align 4 -// CHECK: %[[PTR1:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_16_0_8t(target("dx.CBuffer", { float, double }, 16, 0, 8) %[[HANDLE1]], i32 0) -// CHECK: load float, ptr %[[PTR1]], align 4 +// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", %class.CB, 16, 0, 8), ptr @CB.cb, align 4 +// CHECK: %[[PTR1:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.CBs_16_0_8t(target("dx.CBuffer", %class.CB, 16, 0, 8) %[[HANDLE1]], i32 0) +// CHECK: %a = getelementptr %class.CB, ptr %[[PTR1]], i32 0, i32 0 +// CHECK: load float, ptr %a, align 4 -// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float, double }, 16, 0, 8), ptr @CB1.cb, align 4 -// CHECK: %[[PTR2:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_16_0_8t(target("dx.CBuffer", { float, double }, 16, 0, 8) %[[HANDLE2]], i32 4) -// CHECK: load double, ptr %[[PTR2]], align 8 +// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", %class.CB, 16, 0, 8), ptr @CB.cb, align 4 +// CHECK: %[[PTR2:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.CBs_16_0_8t(target("dx.CBuffer", %class.CB, 16, 0, 8) %[[HANDLE2]], i32 0) +// CHECK: %b = getelementptr %class.CB, ptr %[[PTR2]], i32 0, i32 1 +// CHECK: load double, ptr %b, align 8 -// CHECK: %[[HANDLE3:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4 -// CHECK: %[[PTR3:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t( -// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) %[[HANDLE3]], i32 0) -// CHECK: load i32, ptr %[[PTR3]], align 4 - -// CHECK: %[[HANDLE4:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4 -// CHECK: %[[PTR4:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t( -// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) %[[HANDLE4]], i32 8) -// CHECK: load <2 x float>, ptr %[[PTR4]], align 8 +// CHECK: %[[HANDLE3:[0-9]+]] = load target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20), ptr @ParticleLife.cb, align 4 +// CHECK: %[[PTR3:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.ParticleLifes_24_0_4_8_16_20t(target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20) %[[HANDLE3]], i32 0) +// CHECK: %ParticleTypeMax = getelementptr %class.ParticleLife, ptr %[[PTR3]], i32 0, i32 0 +// CHECK: load i32, ptr %ParticleTypeMax, align 4 -// CHECK: %[[HANDLE5:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4 -// CHECK: %[[PTR5:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t( -// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) %[[HANDLE5]], i32 20) -// CHECK: load float, ptr %[[PTR5]], align 4 +// CHECK: %[[HANDLE4:[0-9]+]] = load target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20), ptr @ParticleLife.cb, align 4 +// CHECK: %[[PTR4:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.ParticleLifes_24_0_4_8_16_20t(target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20) %[[HANDLE4]], i32 0) +// CHECK: %WorldSize = getelementptr %class.ParticleLife, ptr %[[PTR4]], i32 0, i32 2 +// CHECK: %[[VEC:[0-9]+]] = load <2 x float>, ptr %WorldSize, align 8 +// CHECK: extractelement <2 x float> %[[VEC]], i32 1 + +// CHECK: %[[HANDLE5:[0-9]+]] = load target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20), ptr @ParticleLife.cb, align 4 +// CHECK: %[[PTR5:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.ParticleLifes_24_0_4_8_16_20t(target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20) %[[HANDLE5]], i32 0) +// CHECK: %ForceMultipler = getelementptr %class.ParticleLife, ptr %[[PTR5]], i32 0, i32 4 +// CHECK: %15 = load float, ptr %ForceMultipler, align 4 return a + b + ParticleTypeMax + WorldSize.y * ForceMultipler; } @@ -51,12 +57,12 @@ float foo() { // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-NEXT: %CB1_h = call target("dx.CBuffer", { float, double }, 16, 0, 8) -// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_sl_f32f64s_16_0_8t(i32 2, i32 0, i32 1, i32 0, i1 false) -// CHECK-NEXT: store target("dx.CBuffer", { float, double }, 16, 0, 8) %CB1_h, ptr @CB1.cb, align 4 -// CHECK-NEXT: %ParticleLifeCB_h = call target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) -// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t(i32 1, i32 2, i32 1, i32 0, i1 false) -// CHECK-NEXT: store target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20) %ParticleLifeCB_h, ptr @ParticleLifeCB.cb, align 4 +// CHECK-NEXT: %CB_h = call target("dx.CBuffer", %class.CB, 16, 0, 8) +// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_s_class.CBs_16_0_8t(i32 2, i32 0, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", %class.CB, 16, 0, 8) %CB_h, ptr @CB.cb, align 4 +// CHECK-NEXT: %ParticleLife_h = call target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20) +// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_s_class.ParticleLifes_24_0_4_8_16_20t(i32 1, i32 2, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20) %ParticleLife_h, ptr @ParticleLife.cb, align 4 // CHECK: define internal void @_GLOBAL__sub_I_cbuffer.hlsl() // CHECK-NEXT: entry: diff --git a/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl b/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl index 860716ad3e582a..0c2592e32df51d 100644 --- a/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl +++ b/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl @@ -3,9 +3,14 @@ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s // Make sure cbuffer inside namespace works. -// CHECK: @A.cb = external constant target("dx.CBuffer", { float }, 4, 0) -// CHECK: @B.cb = external constant target("dx.CBuffer", { float }, 4, 0) -// CHECK: @C.cb = external constant target("dx.CBuffer", { float }, 4, 0) + +// CHECK: %"class.n0::n1::A" = type { float } +// CHECK: %"class.n0::B" = type { float } +// CHECK: %"class.n0::n2::C" = type { float } + +// CHECK: @A.cb = external constant target("dx.CBuffer", %"class.n0::n1::A", 4, 0) +// CHECK: @B.cb = external constant target("dx.CBuffer", %"class.n0::B", 4, 0) +// CHECK: @C.cb = external constant target("dx.CBuffer", %"class.n0::n2::C", 4, 0) namespace n0 { namespace n1 { @@ -24,19 +29,22 @@ namespace n0 { } float foo() { -// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr @A.cb, align 4 -// CHECK: %[[PTR1:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { float }, 4, 0) %[[HANDLE1]], i32 0) -// CHECK: %[[VAL1:[0-9]+]] = load float, ptr %[[PTR1]], align 4 +// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", %"class.n0::n1::A", 4, 0), ptr @A.cb, align 4 +// CHECK: %[[PTR1:[0-9]+]] = call ptr @"llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.n0::n1::As_4_0t"(target("dx.CBuffer", %"class.n0::n1::A", 4, 0) %[[HANDLE1]], i32 0) +// CHECK: %_ZN2n02n11aE = getelementptr %"class.n0::n1::A", ptr %[[PTR1]], i32 0, i32 0 +// CHECK: %[[VAL1:[0-9]+]] = load float, ptr %_ZN2n02n11aE, align 4 -// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr @B.cb, align 4 -// CHECK: %[[PTR2:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { float }, 4, 0) %[[HANDLE2]], i32 0) -// CHECK: %[[VAL2:[0-9]+]] = load float, ptr %[[PTR2]], align 4 +// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", %"class.n0::B", 4, 0), ptr @B.cb, align 4 +// CHECK: %[[PTR2:[0-9]+]] = call ptr @"llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.n0::Bs_4_0t"(target("dx.CBuffer", %"class.n0::B", 4, 0) %[[HANDLE2]], i32 0) +// CHECK: %_ZN2n01aE = getelementptr %"class.n0::B", ptr %[[PTR2]], i32 0, i32 0 +// CHECK: %[[VAL2:[0-9]+]] = load float, ptr %_ZN2n01aE, align 4 // CHECK: %add = fadd float %[[VAL1]], %[[VAL2]] -// CHECK: %[[HANDLE3:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr @C.cb, align 4 -// CHECK: %[[PTR3:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { float }, 4, 0) %[[HANDLE3]], i32 0) -// CHECK: %[[VAL3:[0-9]+]] = load float, ptr %[[PTR3]], align 4 +// CHECK: %[[HANDLE3:[0-9]+]] = load target("dx.CBuffer", %"class.n0::n2::C", 4, 0), ptr @C.cb, align 4 +// CHECK: %[[PTR3:[0-9]+]] = call ptr @"llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.n0::n2::Cs_4_0t"(target("dx.CBuffer", %"class.n0::n2::C", 4, 0) %[[HANDLE3]], i32 0) +// CHECK: %_ZN2n02n21aE = getelementptr %"class.n0::n2::C", ptr %[[PTR3]], i32 0, i32 0 +// CHECK: %[[VAL3:[0-9]+]] = load float, ptr %_ZN2n02n21aE, align 4 // CHECK: %add1 = fadd float %add, %[[VAL3]] diff --git a/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl b/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl index 58891659179aed..b05c8c044ca4b5 100644 --- a/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl +++ b/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl @@ -2,30 +2,31 @@ // RUN: dxil-pc-shadermodel6.3-compute %s \ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s -// CHECK: @CB.cb = external constant target("dx.CBuffer", { float, double }, 176, 16, 168) +// CHCEK: %class.CB = type { float, double } +// CHECK: @CB.cb = external constant target("dx.CBuffer", %class.CB, 176, 16, 168) cbuffer CB : register(b1, space3) { float a : packoffset(c1.x); double b : packoffset(c10.z); } float foo() { -// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float, double }, 176, 16, 168), ptr @CB.cb, align 4 -// CHECK: %[[PTR1:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_176_16_168t( -// CHECK-SAME: target("dx.CBuffer", { float, double }, 176, 16, 168) %[[HANDLE1]], i32 0) -// CHECK: load float, ptr %[[PTR1]], align 4 +// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", %class.CB, 176, 16, 168), ptr @CB.cb, align 4 +// CHECK: %[[PTR1:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.CBs_176_16_168t(target("dx.CBuffer", %class.CB, 176, 16, 168) %[[HANDLE1]], i32 0) +// CHECK: %a = getelementptr %class.CB, ptr %[[PTR1]], i32 0, i32 0 +// CHECK: load float, ptr %a, align 4 -// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float, double }, 176, 16, 168), ptr @CB.cb, align 4 -// CHECK: %[[PTR2:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_176_16_168t( -// CHECK-SAME: target("dx.CBuffer", { float, double }, 176, 16, 168) %[[HANDLE2]], i32 4) -// CHECK: load double, ptr %[[PTR2]], align 8 +// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", %class.CB, 176, 16, 168), ptr @CB.cb, align 4 +// CHECK: %[[PTR2:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.CBs_176_16_168t(target("dx.CBuffer", %class.CB, 176, 16, 168) %[[HANDLE2]], i32 0) +// CHECK: %b = getelementptr %class.CB, ptr %[[PTR2]], i32 0, i32 1 +// CHECK: load double, ptr %b, align 8 return a + b; } // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-NEXT: %CB_h = call target("dx.CBuffer", { float, double }, 176, 16, 168) -// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_sl_f32f64s_176_16_168t(i32 3, i32 1, i32 1, i32 0, i1 false) -// CHECK-NEXT: store target("dx.CBuffer", { float, double }, 176, 16, 168) %CB_h, ptr @CB.cb, align 4 +// CHECK-NEXT: %CB_h = call target("dx.CBuffer", %class.CB, 176, 16, 168) +// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_s_class.CBs_176_16_168t(i32 3, i32 1, i32 1, i32 0, i1 false) +// CHECK-NEXT: store target("dx.CBuffer", %class.CB, 176, 16, 168) %CB_h, ptr @CB.cb, align 4 [numthreads(4,1,1)] void main() { diff --git a/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl b/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl index c72eac85ca675e..e205f48015977c 100644 --- a/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl +++ b/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl @@ -1,8 +1,10 @@ // RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library %s \ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s +// CHECK: %class.A = type { float } + // CHECK-DAG: @_ZL1b = internal global float 3.000000e+00, align 4 -// CHECK-DAG: @A.cb = external constant target("dx.CBuffer", { float }, 4, 0) +// CHECK-DAG: @A.cb = external constant target("dx.CBuffer", %class.A, 4, 0) // CHECK-NOT: @B.cb cbuffer A { @@ -17,9 +19,10 @@ cbuffer B { // CHECK: define noundef float @_Z3foov() #0 { -// CHECK: %[[HANDLE:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr @A.cb, align 4 -// CHECK: %[[PTR:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { float }, 4, 0) %[[HANDLE]], i32 0) -// CHECK: %[[VAL1:[0-9]+]] = load float, ptr %[[PTR]], align 4 +// CHECK: %[[HANDLE:[0-9]+]] = load target("dx.CBuffer", %class.A, 4, 0), ptr @A.cb, align 4 +// CHECK: %[[PTR:[0-9]+]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.CBuffer_s_class.As_4_0t(target("dx.CBuffer", %class.A, 4, 0) %[[HANDLE]], i32 0) +// CHECK: %a = getelementptr %class.A, ptr %[[PTR]], i32 0, i32 0 +// CHECK: %[[VAL1:[0-9]+]] = load float, ptr %a, align 4 // CHECK: %[[VAL2:[0-9]+]] = load float, ptr @_ZL1b, align 4 // CHECK: %add = fadd float %[[VAL1]], %[[VAL2]] >From a150b1e000e2ecceb504b3fda4690f24bbfd8ecd Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 19 Dec 2024 16:56:10 -0800 Subject: [PATCH 4/4] update tests after merge --- clang/test/CodeGenHLSL/cbuffer.hlsl | 4 ++-- clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl index 77d408c9251cc3..b5be856d994f5b 100644 --- a/clang/test/CodeGenHLSL/cbuffer.hlsl +++ b/clang/test/CodeGenHLSL/cbuffer.hlsl @@ -58,10 +58,10 @@ float foo() { // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: // CHECK-NEXT: %CB_h = call target("dx.CBuffer", %class.CB, 16, 0, 8) -// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_s_class.CBs_16_0_8t(i32 2, i32 0, i32 1, i32 0, i1 false) +// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_s_class.CBs_16_0_8t(i32 2, i32 0, i32 1, i32 0, i1 false) // CHECK-NEXT: store target("dx.CBuffer", %class.CB, 16, 0, 8) %CB_h, ptr @CB.cb, align 4 // CHECK-NEXT: %ParticleLife_h = call target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20) -// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_s_class.ParticleLifes_24_0_4_8_16_20t(i32 1, i32 2, i32 1, i32 0, i1 false) +// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_s_class.ParticleLifes_24_0_4_8_16_20t(i32 1, i32 2, i32 1, i32 0, i1 false) // CHECK-NEXT: store target("dx.CBuffer", %class.ParticleLife, 24, 0, 4, 8, 16, 20) %ParticleLife_h, ptr @ParticleLife.cb, align 4 // CHECK: define internal void @_GLOBAL__sub_I_cbuffer.hlsl() diff --git a/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl b/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl index b05c8c044ca4b5..b6bb8e0428c9c4 100644 --- a/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl +++ b/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl @@ -25,7 +25,7 @@ float foo() { // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: // CHECK-NEXT: %CB_h = call target("dx.CBuffer", %class.CB, 176, 16, 168) -// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_s_class.CBs_176_16_168t(i32 3, i32 1, i32 1, i32 0, i1 false) +// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_s_class.CBs_176_16_168t(i32 3, i32 1, i32 1, i32 0, i1 false) // CHECK-NEXT: store target("dx.CBuffer", %class.CB, 176, 16, 168) %CB_h, ptr @CB.cb, align 4 [numthreads(4,1,1)] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits