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/2] [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/2] 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() && _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits