[clang] [HLSL] Codegen for `cbuffer` declarations without embedded arrays or structs (PR #119755)
Chris B via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 20 07:55:29 PST 2024
================
@@ -54,78 +54,108 @@ 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; }
+
+// Creates resource handle representing the constant buffer.
+// For cbuffer declaration:
//
-// will be translated into
+// cbuffer MyConstants {
+// float a;
+// }
//
-// struct A {
-// float a;
-// float b;
-// } cbuffer_A __attribute__((address_space(4)));
-// float foo() { return cbuffer_A.a + cbuffer_A.b; }
+// creates a structure type MyConstants and then returns the resource handle
+// that would be spelled as:
//
-// 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.
+// __hlsl_resource_t [[hlsl::resource_class(CBuffer)]]
+// [[contained_type(MyConstants)]]
//
-void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) {
- if (Buf.Constants.empty())
- return;
-
- std::vector<llvm::Type *> EltTys;
- for (auto &Const : Buf.Constants) {
- GlobalVariable *GV = Const.first;
- Const.second = EltTys.size();
- llvm::Type *Ty = GV->getValueType();
- EltTys.emplace_back(Ty);
+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);
}
- Buf.LayoutStruct = llvm::StructType::get(EltTys[0]->getContext(), EltTys);
+ 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();
}
-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);
-
- 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 and GEP.
+static void replaceBufferGlobals(CodeGenModule &CGM,
+ CGHLSLRuntime::Buffer &Buf) {
+ assert(Buf.IsCBuffer && "tbuffer codegen is not yet supported");
+
+ GlobalVariable *BufGV = Buf.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-beanz wrote:
```suggestion
// TODO: Map to an hlsl_device address space (#109877).
```
https://github.com/llvm/llvm-project/pull/119755
More information about the cfe-commits
mailing list