[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