[clang] [HLSL] Resource initialization by constructors (PR #135120)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 9 21:29:24 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Helena Kotas (hekota)
<details>
<summary>Changes</summary>
- Adds resource constructor that takes explicit binding for all resource classes.
- Updates implementation of default resource constructor to initialize resource handle to `poison`.
- Removes initialization of resource classes from Codegen.
- Initialization of `cbuffer` still needs to happen in `CGHLSLRuntime` because it does not have a corresponding resource class type.
Design proposal: llvm/wg-hlsl#<!-- -->197
Closes #<!-- -->134154
---
Patch is 75.97 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135120.diff
22 Files Affected:
- (modified) clang/include/clang/Basic/Builtins.td (+12)
- (modified) clang/include/clang/Sema/SemaHLSL.h (+1)
- (modified) clang/lib/CodeGen/CGHLSLBuiltins.cpp (+18)
- (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+28-47)
- (modified) clang/lib/CodeGen/CGHLSLRuntime.h (-1)
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (-3)
- (modified) clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp (+32-4)
- (modified) clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h (+1)
- (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (+2-1)
- (modified) clang/lib/Sema/SemaDecl.cpp (+2-4)
- (modified) clang/lib/Sema/SemaHLSL.cpp (+89)
- (modified) clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl (+36)
- (modified) clang/test/AST/HLSL/StructuredBuffers-AST.hlsl (+58-2)
- (modified) clang/test/AST/HLSL/TypedBuffers-AST.hlsl (+44-1)
- (modified) clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl (+106-23)
- (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl (+1-1)
- (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl (+108-9)
- (modified) clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl (+106-54)
- (modified) clang/test/CodeGenHLSL/cbuffer.hlsl (+4-4)
- (modified) clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl (+2-2)
- (modified) clang/test/CodeGenHLSL/resource-bindings.hlsl (+32-20)
- (modified) clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl (+2-2)
``````````diff
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 868e5b92acdc9..5e92715f59e57 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4789,6 +4789,18 @@ def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLResourceCreatePoisonHandle : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_resource_createpoisonhandle"];
+ let Attributes = [NoThrow];
+ let Prototype = "void(...)";
+}
+
+def HLSLResourceCreateHandleFromBinding : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_resource_createhandlefrombinding"];
+ let Attributes = [NoThrow];
+ let Prototype = "void(...)";
+}
+
def HLSLAll : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_all"];
let Attributes = [NoThrow, Const];
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index f333fe30e8da0..a913d6cce62bd 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -105,6 +105,7 @@ class SemaHLSL : public SemaBase {
HLSLParamModifierAttr::Spelling Spelling);
void ActOnTopLevelFunction(FunctionDecl *FD);
void ActOnVariableDeclarator(VarDecl *VD);
+ bool ActOnUninitializedVarDecl(VarDecl *D);
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU);
void CheckEntryPoint(FunctionDecl *FD);
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 99c62808c323d..dfcade7a074ca 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -287,6 +287,24 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
ArrayRef<Value *>{HandleOp, IndexOp});
}
+ case Builtin::BI__builtin_hlsl_resource_createpoisonhandle: {
+ llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
+ return llvm::PoisonValue::get(HandleTy);
+ }
+ case Builtin::BI__builtin_hlsl_resource_createhandlefrombinding: {
+ llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
+ Value *RegisterNoOp = EmitScalarExpr(E->getArg(1));
+ Value *SpaceNoOp = EmitScalarExpr(E->getArg(2));
+ Value *RangeOp = EmitScalarExpr(E->getArg(3));
+ Value *IndexOp = EmitScalarExpr(E->getArg(4));
+ // FIXME: NonUniformResourceIndex bit is not yet implemented
+ Value *NonUniform =
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(getLLVMContext()), false);
+ return Builder.CreateIntrinsic(
+ HandleTy, CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic(),
+ ArrayRef<Value *>{SpaceNoOp, RegisterNoOp, RangeOp, IndexOp,
+ NonUniform});
+ }
case Builtin::BI__builtin_hlsl_all: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 3b1810b62a2cd..450213fcec676 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -41,8 +41,9 @@ using namespace llvm;
using llvm::hlsl::CBufferRowSizeInBytes;
-static void createResourceInitFn(CodeGenModule &CGM, llvm::GlobalVariable *GV,
- unsigned Slot, unsigned Space);
+static void initializeBufferFromBinding(CodeGenModule &CGM,
+ llvm::GlobalVariable *GV, unsigned Slot,
+ unsigned Space);
namespace {
@@ -255,14 +256,14 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) {
// Add globals for constant buffer elements and create metadata nodes
emitBufferGlobalsAndMetadata(BufDecl, BufGV);
- // Resource initialization
+ // Initialize cbuffer from binding (implicit or explicit)
const HLSLResourceBindingAttr *RBA =
BufDecl->getAttr<HLSLResourceBindingAttr>();
// FIXME: handle implicit binding if no binding attribute is found
// (llvm/llvm-project#110722)
if (RBA)
- createResourceInitFn(CGM, BufGV, RBA->getSlotNumber(),
- RBA->getSpaceNumber());
+ initializeBufferFromBinding(CGM, BufGV, RBA->getSlotNumber(),
+ RBA->getSpaceNumber());
}
llvm::TargetExtType *
@@ -494,15 +495,15 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() {
}
}
-static void createResourceInitFn(CodeGenModule &CGM, llvm::GlobalVariable *GV,
- unsigned Slot, unsigned Space) {
- LLVMContext &Ctx = CGM.getLLVMContext();
- llvm::Type *Int1Ty = llvm::Type::getInt1Ty(Ctx);
+static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
+ Intrinsic::ID IntrID,
+ ArrayRef<llvm::Value *> Args) {
+ LLVMContext &Ctx = CGM.getLLVMContext();
llvm::Function *InitResFunc = llvm::Function::Create(
llvm::FunctionType::get(CGM.VoidTy, false),
llvm::GlobalValue::InternalLinkage,
- ("_init_resource_" + GV->getName()).str(), CGM.getModule());
+ ("_init_buffer_" + GV->getName()).str(), CGM.getModule());
InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
llvm::BasicBlock *EntryBB =
@@ -511,28 +512,12 @@ static void createResourceInitFn(CodeGenModule &CGM, llvm::GlobalVariable *GV,
const DataLayout &DL = CGM.getModule().getDataLayout();
Builder.SetInsertPoint(EntryBB);
- // Make sure the global variable is resource handle (cbuffer) or
- // resource class (=class where the first element is a resource handle).
+ // Make sure the global variable is buffer resource handle
llvm::Type *HandleTy = GV->getValueType();
- assert((HandleTy->isTargetExtTy() ||
- (HandleTy->isStructTy() &&
- HandleTy->getStructElementType(0)->isTargetExtTy())) &&
- "unexpected type of the global");
- if (!HandleTy->isTargetExtTy())
- HandleTy = HandleTy->getStructElementType(0);
+ assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
- llvm::Value *Args[] = {
- llvm::ConstantInt::get(CGM.IntTy, Space), /* reg_space */
- llvm::ConstantInt::get(CGM.IntTy, Slot), /* lower_bound */
- // FIXME: resource arrays are not yet implemented
- llvm::ConstantInt::get(CGM.IntTy, 1), /* range_size */
- llvm::ConstantInt::get(CGM.IntTy, 0), /* index */
- // FIXME: NonUniformResourceIndex bit is not yet implemented
- llvm::ConstantInt::get(Int1Ty, false) /* non-uniform */
- };
llvm::Value *CreateHandle = Builder.CreateIntrinsic(
- /*ReturnType=*/HandleTy,
- CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic(), Args, nullptr,
+ /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
Twine(GV->getName()).concat("_h"));
llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
@@ -543,24 +528,20 @@ static void createResourceInitFn(CodeGenModule &CGM, llvm::GlobalVariable *GV,
CGM.AddCXXGlobalInit(InitResFunc);
}
-void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD,
- llvm::GlobalVariable *GV) {
-
- // If the global variable has resource binding, create an init function
- // for the resource
- const HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
- if (!RBA)
- // FIXME: collect unbound resources for implicit binding resolution later
- // on?
- return;
-
- if (!VD->getType().getTypePtr()->isHLSLResourceRecord())
- // FIXME: Only simple declarations of resources are supported for now.
- // Arrays of resources or resources in user defined classes are
- // not implemented yet.
- return;
-
- createResourceInitFn(CGM, GV, RBA->getSlotNumber(), RBA->getSpaceNumber());
+static void initializeBufferFromBinding(CodeGenModule &CGM,
+ llvm::GlobalVariable *GV, unsigned Slot,
+ unsigned Space) {
+ llvm::Type *Int1Ty = llvm::Type::getInt1Ty(CGM.getLLVMContext());
+ llvm::Value *Args[] = {
+ llvm::ConstantInt::get(CGM.IntTy, Space), /* reg_space */
+ llvm::ConstantInt::get(CGM.IntTy, Slot), /* lower_bound */
+ llvm::ConstantInt::get(CGM.IntTy, 1), /* range_size */
+ llvm::ConstantInt::get(CGM.IntTy, 0), /* index */
+ llvm::ConstantInt::get(Int1Ty, false) /* non-uniform */
+ };
+ initializeBuffer(CGM, GV,
+ CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic(),
+ Args);
}
llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 68151c0f0ea24..4d6db3f5d9f3e 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -150,7 +150,6 @@ class CGHLSLRuntime {
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn);
void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn);
- void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var);
llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB);
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 8f9cf965af2b9..395b5c3ecc695 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -5698,9 +5698,6 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
getCUDARuntime().handleVarRegistration(D, *GV);
}
- if (LangOpts.HLSL)
- getHLSLRuntime().handleGlobalVarDefinition(D, GV);
-
GV->setInitializer(Init);
if (emitter)
emitter->finalize(GV);
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 2d3e1088557ab..a680d6efcd67d 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -400,6 +400,7 @@ void BuiltinTypeMethodBuilder::createDecl() {
// create params & set them to the function prototype
SmallVector<ParmVarDecl *> ParmDecls;
+ unsigned CurScopeDepth = DeclBuilder.SemaRef.getCurScope()->getDepth();
auto FnProtoLoc =
Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
for (int I = 0, E = Params.size(); I != E; I++) {
@@ -414,6 +415,7 @@ void BuiltinTypeMethodBuilder::createDecl() {
HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
Parm->addAttr(Mod);
}
+ Parm->setScopeInfo(CurScopeDepth, I);
ParmDecls.push_back(Parm);
FnProtoLoc.setParam(I, Parm);
}
@@ -447,10 +449,14 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
AST, NestedNameSpecifierLoc(), SourceLocation(), FD, false,
FD->getNameInfo(), AST.BuiltinFnTy, VK_PRValue);
+ auto *ImpCast = ImplicitCastExpr::Create(
+ AST, AST.getPointerType(FD->getType()), CK_BuiltinFnToFnPtr, DRE, nullptr,
+ VK_PRValue, FPOptionsOverride());
+
if (ReturnType.isNull())
ReturnType = FD->getReturnType();
- Expr *Call = CallExpr::Create(AST, DRE, Args, ReturnType, VK_PRValue,
+ Expr *Call = CallExpr::Create(AST, ImpCast, Args, ReturnType, VK_PRValue,
SourceLocation(), FPOptionsOverride());
StmtsList.push_back(Call);
return *this;
@@ -632,11 +638,33 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
if (Record->isCompleteDefinition())
return *this;
- // FIXME: initialize handle to poison value; this can be added after
- // resource constructor from binding is implemented, otherwise the handle
- // value will get overwritten.
+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+ QualType HandleType = getResourceHandleField()->getType();
return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
false, true)
+ .callBuiltin("__builtin_hlsl_resource_createpoisonhandle", HandleType,
+ PH::Handle)
+ .assign(PH::Handle, PH::LastStmt)
+ .finalize();
+}
+
+BuiltinTypeDeclBuilder &
+BuiltinTypeDeclBuilder::addHandleConstructorFromBinding() {
+ if (Record->isCompleteDefinition())
+ return *this;
+
+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+ ASTContext &AST = SemaRef.getASTContext();
+ QualType HandleType = getResourceHandleField()->getType();
+
+ return BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true)
+ .addParam("registerNo", AST.UnsignedIntTy)
+ .addParam("spaceNo", AST.UnsignedIntTy)
+ .addParam("range", AST.IntTy)
+ .addParam("index", AST.UnsignedIntTy)
+ .callBuiltin("__builtin_hlsl_resource_createhandlefrombinding",
+ HandleType, PH::Handle, PH::_0, PH::_1, PH::_2, PH::_3)
+ .assign(PH::Handle, PH::LastStmt)
.finalize();
}
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index dbf54dfd9ecd9..db617dc53c899 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -78,6 +78,7 @@ class BuiltinTypeDeclBuilder {
// Builtin types methods
BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
+ BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
// Builtin types methods
BuiltinTypeDeclBuilder &addLoadMethods();
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index f5477ac912693..f09232a9db4da 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -131,7 +131,8 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
bool RawBuffer) {
return BuiltinTypeDeclBuilder(S, Decl)
.addHandleMember(RC, IsROV, RawBuffer)
- .addDefaultHandleConstructor();
+ .addDefaultHandleConstructor()
+ .addHandleConstructorFromBinding();
}
// This function is responsible for constructing the constraint expression for
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 540f5f23fe89a..22699644c0a1a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14345,10 +14345,8 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
Var->getType().getAddressSpace() == LangAS::opencl_local)
return;
- // In HLSL, objects in the hlsl_constant address space are initialized
- // externally, so don't synthesize an implicit initializer.
- if (getLangOpts().HLSL &&
- Var->getType().getAddressSpace() == LangAS::hlsl_constant)
+ // Handle HLSL uninitialized decls
+ if (getLangOpts().HLSL && HLSL().ActOnUninitializedVarDecl(Var))
return;
// C++03 [dcl.init]p9:
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index fe600386e6fa9..27959f61f1dc3 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -32,6 +32,7 @@
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Template.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -305,6 +306,10 @@ static bool isResourceRecordTypeOrArrayOf(const Type *Ty) {
return HLSLAttributedResourceType::findHandleTypeOnResource(Ty) != nullptr;
}
+static bool isResourceRecordTypeOrArrayOf(VarDecl *VD) {
+ return isResourceRecordTypeOrArrayOf(VD->getType().getTypePtr());
+}
+
// Returns true if the type is a leaf element type that is not valid to be
// included in HLSL Buffer, such as a resource class, empty struct, zero-sized
// array, or a builtin intangible type. Returns false it is a valid leaf element
@@ -2385,6 +2390,29 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
break;
}
+ case Builtin::BI__builtin_hlsl_resource_createpoisonhandle: {
+ if (SemaRef.checkArgCount(TheCall, 1) ||
+ CheckResourceHandle(&SemaRef, TheCall, 0))
+ return true;
+ // use the type of the handle (arg0) as a return type
+ QualType ResourceTy = TheCall->getArg(0)->getType();
+ TheCall->setType(ResourceTy);
+ break;
+ }
+ case Builtin::BI__builtin_hlsl_resource_createhandlefrombinding: {
+ ASTContext &AST = SemaRef.getASTContext();
+ if (SemaRef.checkArgCount(TheCall, 5) ||
+ CheckResourceHandle(&SemaRef, TheCall, 0) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy))
+ return true;
+ // use the type of the handle (arg0) as a return type
+ QualType ResourceTy = TheCall->getArg(0)->getType();
+ TheCall->setType(ResourceTy);
+ break;
+ }
case Builtin::BI__builtin_hlsl_and:
case Builtin::BI__builtin_hlsl_or: {
if (SemaRef.checkArgCount(TheCall, 2))
@@ -3179,6 +3207,67 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {
}
}
+static bool initVarDeclWithCtor(Sema &S, VarDecl *VD,
+ MutableArrayRef<Expr *> Args) {
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VD);
+ InitializationKind Kind = InitializationKind::CreateDirect(
+ VD->getLocation(), SourceLocation(), SourceLocation());
+
+ InitializationSequence InitSeq(S, Entity, Kind, Args);
+ ExprResult Init = InitSeq.Perform(S, Entity, Kind, Args);
+
+ if (!Init.get())
+ return false;
+
+ VD->setInit(S.MaybeCreateExprWithCleanups(Init.get()));
+ VD->setInitStyle(VarDecl::CallInit);
+ S.CheckCompleteVariableDeclaration(VD);
+ return true;
+}
+
+static bool initGlobalResourceDecl(Sema &S, VarDecl *VD) {
+ HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
+ if (!RBA)
+ // FIXME: add support for implicit binding (llvm/llvm-project#110722)
+ return false;
+
+ ASTContext &AST = S.getASTContext();
+ uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
+ uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
+ Expr *Args[] = {
+ IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, RBA->getSlotNumber()),
+ AST.UnsignedIntTy, SourceLocation()),
+ IntegerLiteral::Create(AST,
+ llvm::APInt(UIntTySize, RBA->getSpaceNumber()),
+ AST.UnsignedIntTy, SourceLocation()),
+ IntegerLiteral::Create(AST, llvm::APInt(IntTySize, 1), AST.IntTy,
+ SourceLocation()),
+ IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy,
+ SourceLocation())};
+
+ return initVarDeclWithCtor(S, VD, Args);
+}
+
+// Returns true in the initialization has been handled;
+// Return false to let Clang handle the default initializaton.
+bool SemaHLSL::ActOnUninitializedVarDecl(VarDecl *VD) {
+ // Objects in the hlsl_constant address space are initialized
+ // externally, so don't synthesize an implicit initializer.
+ if (VD->getType().getAddressSpace() == LangAS::hlsl_constant)
+ return true;
+
+ // Initialize resources
+ if (!isResourceRecordTypeOrArrayOf(VD))
+ return false;
+
+ // FIXME: We currectly support only simple resources - no arrays of resources
+ // or resources in user defined structs).
+ if (VD->getType()->isHLSLResourceRecord())
+ return initGlobalResourceDecl(SemaRef, VD);
+
+ return false;
+}
+
// Walks though the global variable declaration, collects all resource binding
// requirements and adds them to Bindings
void SemaHLSL::collectResourceBindingsOnVarDecl(VarDecl *VD) {
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 38e5b6281c42e..c8b584171f007 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -42,5 +42,41 @@ RESOURCE Buffer;
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(char8_t)]]
+// Default constructor
+
+// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void ()' inline
+// CHECK-...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/135120
More information about the cfe-commits
mailing list