[clang] [llvm] [HLSL] Use static create methods to initialize individual resources (PR #156544)
Helena Kotas via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 12 14:32:32 PDT 2025
https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/156544
>From 7a0d3ca684a2d95e0528d5f4ee77bc1306ddfe1d Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 28 Aug 2025 08:17:31 -0700
Subject: [PATCH 01/12] [HLSL] Reorder the arguments of handle initialization
builtins
Reorder the arguments of handle initialization builtins to match the order of the
llvm intrinsics, and also to match the arguments on the static create methods for
resources (coming soon).
---
clang/lib/CodeGen/CGHLSLBuiltins.cpp | 8 ++++----
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 2 +-
clang/lib/Sema/SemaHLSL.cpp | 4 ++--
clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 2 +-
clang/test/AST/HLSL/StructuredBuffers-AST.hlsl | 2 +-
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 2 +-
6 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 58165185b6711..483920f2392cd 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -348,10 +348,10 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
}
case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
- Value *SpaceOp = EmitScalarExpr(E->getArg(1));
- Value *RangeOp = EmitScalarExpr(E->getArg(2));
- Value *IndexOp = EmitScalarExpr(E->getArg(3));
- Value *OrderID = EmitScalarExpr(E->getArg(4));
+ Value *OrderID = EmitScalarExpr(E->getArg(1));
+ Value *SpaceOp = EmitScalarExpr(E->getArg(2));
+ Value *RangeOp = EmitScalarExpr(E->getArg(3));
+ Value *IndexOp = EmitScalarExpr(E->getArg(4));
Value *Name = EmitScalarExpr(E->getArg(5));
// FIXME: NonUniformResourceIndex bit is not yet implemented
// (llvm/llvm-project#135452)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 806800cb7b213..7830cdd18c6cd 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -670,7 +670,7 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
.addParam("orderId", AST.UnsignedIntTy)
.addParam("name", AST.getPointerType(AST.CharTy.withConst()))
.callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
- HandleType, PH::Handle, PH::_0, PH::_1, PH::_2, PH::_3,
+ HandleType, PH::Handle, PH::_3, PH::_0, PH::_1, PH::_2,
PH::_4)
.assign(PH::Handle, PH::LastStmt)
.finalize();
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 6a68fa2ed7a8b..c12b35308e127 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2853,8 +2853,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaRef.checkArgCount(TheCall, 6) ||
CheckResourceHandle(&SemaRef, TheCall, 0) ||
CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.IntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.UnsignedIntTy) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
AST.getPointerType(AST.CharTy.withConst())))
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index f85194496942b..90794eb69ef46 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -97,10 +97,10 @@ RESOURCE Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding'
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
-// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
// CHECK-NEXT: AlwaysInlineAttr
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index 6ee7145c7e538..e028936e397ac 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -144,10 +144,10 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding'
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
-// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
// CHECK-NEXT: AlwaysInlineAttr
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index e7f000e9c1b70..02c8cf86c8c8b 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -119,10 +119,10 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding'
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
-// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
// CHECK-NEXT: AlwaysInlineAttr
>From dcbbda45ce7d3341ad74025a02b3f8c9b0391dc0 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 28 Aug 2025 08:22:41 -0700
Subject: [PATCH 02/12] [HLSL] Add static methods for resource initialization
and a constructor from handle
Adds static methods `__createFromBinding` and `__createFromImplicitBinding`
to resource classes. These methods will be used for resource initialization
instead of the resource constructors that take binding information.
Also adds a private resource constructor that takes an initialized resource handle.
This constructor will be called from the static create methods.
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 169 ++++++++++++++++--
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 9 +-
clang/lib/Sema/HLSLExternalSemaSource.cpp | 5 +-
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 67 ++++++-
.../test/AST/HLSL/StructuredBuffers-AST.hlsl | 63 +++++++
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 63 +++++++
clang/test/SemaHLSL/Language/InitLists.hlsl | 1 +
7 files changed, 354 insertions(+), 23 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 7830cdd18c6cd..4eac9043dab86 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaHLSL.h"
@@ -110,8 +111,11 @@ struct BuiltinTypeMethodBuilder {
CXXMethodDecl *Method;
bool IsConst;
bool IsCtor;
+ AccessSpecifier Access;
+ StorageClass SC;
llvm::SmallVector<Param> Params;
llvm::SmallVector<Stmt *> StmtsList;
+ llvm::SmallVector<VarDecl *> LocalVars;
// Argument placeholders, inspired by std::placeholder. These are the indices
// of arguments to forward to `callBuiltin` and other method builder methods.
@@ -120,7 +124,16 @@ struct BuiltinTypeMethodBuilder {
// LastStmt - refers to the last statement in the method body; referencing
// LastStmt will remove the statement from the method body since
// it will be linked from the new expression being constructed.
- enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128, LastStmt };
+ enum class PlaceHolder {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ LocalVar_0 = 64,
+ Handle = 128,
+ LastStmt
+ };
Expr *convertPlaceholder(PlaceHolder PH);
Expr *convertPlaceholder(Expr *E) { return E; }
@@ -130,13 +143,17 @@ struct BuiltinTypeMethodBuilder {
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
QualType ReturnTy, bool IsConst = false,
- bool IsCtor = false)
+ bool IsCtor = false,
+ AccessSpecifier Access = AS_public,
+ StorageClass SC = SC_None)
: DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
- IsConst(IsConst), IsCtor(IsCtor) {}
+ IsConst(IsConst), IsCtor(IsCtor), Access(Access), SC(SC) {}
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, StringRef NameStr,
QualType ReturnTy, bool IsConst = false,
- bool IsCtor = false);
+ bool IsCtor = false,
+ AccessSpecifier Access = AS_public,
+ StorageClass SC = SC_None);
BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other) = delete;
~BuiltinTypeMethodBuilder() { finalize(); }
@@ -147,13 +164,15 @@ struct BuiltinTypeMethodBuilder {
BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
HLSLParamModifierAttr::Spelling Modifier =
HLSLParamModifierAttr::Keyword_in);
+ BuiltinTypeMethodBuilder &createLocalVar(StringRef Name, QualType Ty);
template <typename... Ts>
BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
QualType ReturnType, Ts... ArgSpecs);
+ template <typename T> BuiltinTypeMethodBuilder &callHandleCtor(T HandleExpr);
template <typename TLHS, typename TRHS>
BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
- BuiltinTypeDeclBuilder &finalize();
+ BuiltinTypeDeclBuilder &finalize(CXXMethodDecl **OutMethod = nullptr);
Expr *getResourceHandleExpr();
private:
@@ -328,6 +347,17 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
}
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ if (PH >= PlaceHolder::LocalVar_0) {
+ unsigned Index = static_cast<unsigned>(PH) -
+ static_cast<unsigned>(PlaceHolder::LocalVar_0);
+ assert(Index < LocalVars.size() && "local var index out of range");
+ VarDecl *VD = LocalVars[Index];
+ return DeclRefExpr::Create(
+ AST, NestedNameSpecifierLoc(), SourceLocation(), VD, false,
+ DeclarationNameInfo(VD->getDeclName(), SourceLocation()), VD->getType(),
+ VK_LValue);
+ }
+
ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
return DeclRefExpr::Create(
AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
@@ -335,12 +365,11 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
ParamDecl->getType(), VK_PRValue);
}
-BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB,
- StringRef NameStr,
- QualType ReturnTy,
- bool IsConst, bool IsCtor)
+BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(
+ BuiltinTypeDeclBuilder &DB, StringRef NameStr, QualType ReturnTy,
+ bool IsConst, bool IsCtor, AccessSpecifier Access, StorageClass SC)
: DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
- IsCtor(IsCtor) {
+ IsCtor(IsCtor), Access(Access), SC(SC) {
assert((!NameStr.empty() || IsCtor) && "method needs a name");
assert(((IsCtor && !IsConst) || !IsCtor) && "constructor cannot be const");
@@ -390,10 +419,9 @@ void BuiltinTypeMethodBuilder::createDecl() {
ExplicitSpecifier(), false, true, false,
ConstexprSpecKind::Unspecified);
else
- Method =
- CXXMethodDecl::Create(AST, DeclBuilder.Record, SourceLocation(),
- NameInfo, FuncTy, TSInfo, SC_None, false, false,
- ConstexprSpecKind::Unspecified, SourceLocation());
+ Method = CXXMethodDecl::Create(
+ AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo, SC,
+ false, false, ConstexprSpecKind::Unspecified, SourceLocation());
// create params & set them to the function prototype
SmallVector<ParmVarDecl *> ParmDecls;
@@ -431,15 +459,31 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
OK_Ordinary);
}
+BuiltinTypeMethodBuilder &
+BuiltinTypeMethodBuilder::createLocalVar(StringRef Name, QualType Ty) {
+ ensureCompleteDecl();
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ VarDecl *VD =
+ VarDecl::Create(AST, Method, SourceLocation(), SourceLocation(),
+ &AST.Idents.get(Name, tok::TokenKind::identifier), Ty,
+ AST.getTrivialTypeSourceInfo(Ty), SC_None);
+ LocalVars.push_back(VD);
+ DeclStmt *DS = new (AST)
+ clang::DeclStmt(DeclGroupRef(VD), SourceLocation(), SourceLocation());
+ StmtsList.push_back(DS);
+ return *this;
+}
+
template <typename... Ts>
BuiltinTypeMethodBuilder &
BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
QualType ReturnType, Ts... ArgSpecs) {
+ ensureCompleteDecl();
+
std::array<Expr *, sizeof...(ArgSpecs)> Args{
convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
- ensureCompleteDecl();
-
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
DeclRefExpr *DRE = DeclRefExpr::Create(
@@ -459,6 +503,25 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
return *this;
}
+template <typename T>
+BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::callHandleCtor(T Handle) {
+ ensureCompleteDecl();
+
+ Expr *HandleExpr = convertPlaceholder(Handle);
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(DeclBuilder.Record));
+ CXXConstructorDecl *Ctor = DeclBuilder.HandleCtor;
+ assert(Ctor && "Handle constructor not created");
+
+ CXXConstructExpr *CtorExpr = CXXConstructExpr::Create(
+ AST, RecordType, SourceLocation(), Ctor, false, {HandleExpr}, false,
+ false, false, false, CXXConstructionKind::Complete, SourceRange());
+
+ StmtsList.push_back(CtorExpr);
+ return *this;
+}
+
template <typename TLHS, typename TRHS>
BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::assign(TLHS LHS, TRHS RHS) {
Expr *LHSExpr = convertPlaceholder(LHS);
@@ -483,7 +546,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
return *this;
}
-BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
+BuiltinTypeDeclBuilder &
+BuiltinTypeMethodBuilder::finalize(CXXMethodDecl **OutMethod) {
assert(!DeclBuilder.Record->isCompleteDefinition() &&
"record is already complete");
@@ -510,11 +574,13 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
SourceLocation(), SourceLocation()));
Method->setLexicalDeclContext(DeclBuilder.Record);
- Method->setAccess(AccessSpecifier::AS_public);
+ Method->setAccess(Access);
Method->addAttr(AlwaysInlineAttr::CreateImplicit(
AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
DeclBuilder.Record->addDecl(Method);
}
+ if (OutMethod)
+ *OutMethod = Method;
return DeclBuilder;
}
@@ -619,7 +685,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
// Adds default constructor to the resource class:
// Resource::Resource()
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor() {
if (Record->isCompleteDefinition())
return *this;
@@ -633,6 +699,23 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
.finalize();
}
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleConstructor() {
+ if (Record->isCompleteDefinition())
+ return *this;
+
+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+ ASTContext &AST = SemaRef.getASTContext();
+ QualType HandleType = getResourceHandleField()->getType();
+ CXXMethodDecl *OutMethod = nullptr;
+
+ BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true, AS_public)
+ .addParam("handle", HandleType)
+ .assign(PH::Handle, PH::_0)
+ .finalize(&OutMethod);
+ HandleCtor = cast<CXXConstructorDecl>(OutMethod);
+ return *this;
+}
+
BuiltinTypeDeclBuilder &
BuiltinTypeDeclBuilder::addHandleConstructorFromBinding() {
if (Record->isCompleteDefinition())
@@ -676,6 +759,54 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
.finalize();
}
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
+ if (Record->isCompleteDefinition())
+ return *this;
+
+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+ ASTContext &AST = SemaRef.getASTContext();
+ QualType HandleType = getResourceHandleField()->getType();
+ QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
+
+ return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
+ false, false, AS_public, SC_Static)
+ .addParam("registerNo", AST.UnsignedIntTy)
+ .addParam("spaceNo", AST.UnsignedIntTy)
+ .addParam("range", AST.IntTy)
+ .addParam("index", AST.UnsignedIntTy)
+ .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
+ .createLocalVar("tmp", HandleType)
+ .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
+ PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
+ .callHandleCtor(PH::LastStmt)
+ .finalize();
+}
+
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
+ if (Record->isCompleteDefinition())
+ return *this;
+
+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+ ASTContext &AST = SemaRef.getASTContext();
+ QualType HandleType = getResourceHandleField()->getType();
+ QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
+
+ return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
+ RecordType, false, false, AS_public,
+ SC_Static)
+ .addParam("orderId", AST.UnsignedIntTy)
+ .addParam("spaceNo", AST.UnsignedIntTy)
+ .addParam("range", AST.IntTy)
+ .addParam("index", AST.UnsignedIntTy)
+ .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
+ .createLocalVar("tmp", HandleType)
+ .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
+ HandleType, PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3,
+ PH::_4)
+ .callHandleCtor(PH::LastStmt)
+ .finalize();
+}
+
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
ASTContext &AST = Record->getASTContext();
DeclarationName Subscript =
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 098b72692bd3a..be67e150775e2 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -25,6 +25,7 @@ namespace clang {
class ClassTemplateDecl;
class NamespaceDecl;
class CXXRecordDecl;
+class CXXConstructorDecl;
class FieldDecl;
namespace hlsl {
@@ -52,6 +53,7 @@ class BuiltinTypeDeclBuilder {
ClassTemplateDecl *PrevTemplate = nullptr;
NamespaceDecl *HLSLNamespace = nullptr;
llvm::StringMap<FieldDecl *> Fields;
+ CXXConstructorDecl *HandleCtor = nullptr;
public:
friend struct TemplateParameterListBuilder;
@@ -77,10 +79,15 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &addArraySubscriptOperators();
// Builtin types constructors
- BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
+ BuiltinTypeDeclBuilder &addDefaultConstructor();
+ BuiltinTypeDeclBuilder &addHandleConstructor();
BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
+ // Static create methods
+ BuiltinTypeDeclBuilder &addCreateFromBinding();
+ BuiltinTypeDeclBuilder &addCreateFromImplicitBinding();
+
// Builtin types methods
BuiltinTypeDeclBuilder &addLoadMethods();
BuiltinTypeDeclBuilder &addIncrementCounterMethod();
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 726581d131623..17843c4e6c751 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -131,7 +131,10 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
bool RawBuffer) {
return BuiltinTypeDeclBuilder(S, Decl)
.addHandleMember(RC, IsROV, RawBuffer)
- .addDefaultHandleConstructor()
+ .addDefaultConstructor()
+ .addHandleConstructor()
+ .addCreateFromBinding()
+ .addCreateFromImplicitBinding()
.addHandleConstructorFromBinding()
.addHandleConstructorFromImplicitBinding();
}
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 90794eb69ef46..8336bf00ed4cb 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -56,6 +56,69 @@ RESOURCE Buffer;
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
+// Constructor from handle
+
+// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (__hlsl_resource_t
+// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(char8_t)]]
+// CHECK-SAME: )' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 'handle' '__hlsl_resource_t {{.*}}
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromBinding 'hlsl::[[RESOURCE]] (unsigned int, unsigned int, int, unsigned int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} registerNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromImplicitBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromImplicitBinding 'hlsl::[[RESOURCE]] (unsigned int, unsigned int, int, unsigned int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} orderId 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: DeclStmt {{.*}}
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// Constructor from binding
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline
@@ -104,5 +167,5 @@ RESOURCE Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
// CHECK-NEXT: AlwaysInlineAttr
-// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const element_type &(unsigned int) const'
-// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'element_type &(unsigned int)'
+// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const char8_t &(unsigned int) const'
+// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'char8_t &(unsigned int)'
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index e028936e397ac..ad481ca68b248 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -103,6 +103,69 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
+// Constructor from handle
+// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (__hlsl_resource_t
+// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME: )' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 'handle' '__hlsl_resource_t {{.*}}
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromBinding 'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} registerNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromImplicitBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromImplicitBinding 'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} orderId 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: DeclStmt {{.*}}
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// Constructor from binding
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 02c8cf86c8c8b..3484d088eb17a 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -78,6 +78,69 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
+// Constructor from handle
+
+// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (__hlsl_resource_t
+// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME: )' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 'handle' '__hlsl_resource_t {{.*}}
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromBinding 'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} registerNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromImplicitBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromImplicitBinding 'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} orderId 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: DeclStmt {{.*}}
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// Constructor from binding
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline
diff --git a/clang/test/SemaHLSL/Language/InitLists.hlsl b/clang/test/SemaHLSL/Language/InitLists.hlsl
index 3607dfd8aedbc..524f6ac220092 100644
--- a/clang/test/SemaHLSL/Language/InitLists.hlsl
+++ b/clang/test/SemaHLSL/Language/InitLists.hlsl
@@ -124,3 +124,4 @@ void Err2(RWBuffer<float4> B) {
// These notes refer to the RWBuffer constructors that do not have source locations
// expected-note@*{{candidate constructor (the implicit copy constructor) not viable}}
// expected-note@*{{candidate constructor (the implicit move constructor) not viable}}
+// expected-note@*{{candidate constructor not viable}}
>From 02342c922d0feec12b980528eb4a75e8d6676ebe Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 2 Sep 2025 15:03:11 -0700
Subject: [PATCH 03/12] [HLSL] Use static create methods to initialize
individual resources
---
clang/lib/Sema/SemaHLSL.cpp | 128 +++++++--
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 2 +-
clang/test/AST/HLSL/vk_binding_attr.hlsl | 48 +++-
.../CodeGenHLSL/GlobalConstructorLib.hlsl | 6 +-
.../debug/rwbuffer_debug_info.hlsl | 5 +-
.../ByteAddressBuffers-constructors.hlsl | 66 ++---
.../resources/RWBuffer-constructor.hlsl | 76 +++---
.../StructuredBuffers-constructors.hlsl | 69 +++--
.../resources/resource-bindings.hlsl | 20 +-
clang/test/CodeGenHLSL/static-local-ctor.hlsl | 2 +-
out.ll | 251 ++++++++++++++++++
11 files changed, 508 insertions(+), 165 deletions(-)
create mode 100644 out.ll
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c12b35308e127..88334908073a0 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1201,6 +1201,14 @@ struct PerVisibilityBindingChecker {
}
};
+static CXXMethodDecl *lookupMethod(CXXRecordDecl *Record, StringRef Name,
+ StorageClass SC = SC_None) {
+ for (auto *Method : Record->methods())
+ if (Method->getStorageClass() == SC && Method->getName() == Name)
+ return Method;
+ return nullptr;
+}
+
} // end anonymous namespace
bool SemaHLSL::handleRootSignatureElements(
@@ -3689,26 +3697,6 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {
deduceAddressSpace(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);
- if (InitSeq.Failed())
- return false;
-
- 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;
-}
-
void SemaHLSL::createResourceRecordCtorArgs(
const Type *ResourceTy, StringRef VarName, HLSLResourceBindingAttr *RBA,
HLSLVkBindingAttr *VkBinding, uint32_t ArrayIndex,
@@ -3759,11 +3747,101 @@ void SemaHLSL::createResourceRecordCtorArgs(
}
bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
- SmallVector<Expr *> Args;
- createResourceRecordCtorArgs(VD->getType().getTypePtr(), VD->getName(),
- VD->getAttr<HLSLResourceBindingAttr>(),
- VD->getAttr<HLSLVkBindingAttr>(), 0, Args);
- return initVarDeclWithCtor(SemaRef, VD, Args);
+ assert(VD->getType()->isHLSLResourceRecord() &&
+ "expected resource record type");
+
+ ASTContext &AST = SemaRef.getASTContext();
+ uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
+ uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
+
+ // Gather resource binding information from attributes.
+ HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
+ HLSLVkBindingAttr *VkBinding = VD->getAttr<HLSLVkBindingAttr>();
+ std::optional<uint32_t> RegisterSlot;
+ uint32_t SpaceNo = 0;
+ if (VkBinding) {
+ RegisterSlot = VkBinding->getBinding();
+ SpaceNo = VkBinding->getSet();
+ } else if (RBA) {
+ if (RBA->hasRegisterSlot())
+ RegisterSlot = RBA->getSlotNumber();
+ SpaceNo = RBA->getSpaceNumber();
+ }
+
+ // Find correct initialization method and create its argumentss.
+ QualType ResourceTy = VD->getType();
+ CXXRecordDecl *ResourceDecl = ResourceTy->getAsCXXRecordDecl();
+ CXXMethodDecl *CreateMethod = nullptr;
+ llvm::SmallVector<Expr *> Args;
+
+ if (RegisterSlot.has_value()) {
+ // The resource has explicit binding.
+ CreateMethod = lookupMethod(ResourceDecl, "__createFromBinding", SC_Static);
+ IntegerLiteral *RegSlot = IntegerLiteral::Create(
+ AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.UnsignedIntTy,
+ SourceLocation());
+ Args.push_back(RegSlot);
+ } else {
+ // The resource has implicit binding.
+ CreateMethod =
+ lookupMethod(ResourceDecl, "__createFromImplicitBinding", SC_Static);
+ uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID())
+ ? RBA->getImplicitBindingOrderID()
+ : getNextImplicitBindingOrderID();
+ IntegerLiteral *OrderId =
+ IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID),
+ AST.UnsignedIntTy, SourceLocation());
+ Args.push_back(OrderId);
+ }
+
+ if (!CreateMethod)
+ return false;
+
+ IntegerLiteral *Space =
+ IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, SpaceNo),
+ AST.UnsignedIntTy, SourceLocation());
+ Args.push_back(Space);
+
+ IntegerLiteral *RangeSize = IntegerLiteral::Create(
+ AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());
+ Args.push_back(RangeSize);
+
+ IntegerLiteral *Index = IntegerLiteral::Create(
+ AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());
+ Args.push_back(Index);
+
+ StringRef VarName = VD->getName();
+ StringLiteral *Name = StringLiteral::Create(
+ AST, VarName, StringLiteralKind::Ordinary, false,
+ AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()),
+ SourceLocation());
+ ImplicitCastExpr *NameCast = ImplicitCastExpr::Create(
+ AST, AST.getPointerType(AST.CharTy.withConst()), CK_ArrayToPointerDecay,
+ Name, nullptr, VK_PRValue, FPOptionsOverride());
+ Args.push_back(NameCast);
+
+ // Make sure the create method template is instantiated and emitted.
+ if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
+ SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
+ true);
+
+ // Create CallExpr with a call to the static method and set it as the decl
+ // initialization.
+ DeclRefExpr *DRE = DeclRefExpr::Create(
+ AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false,
+ CreateMethod->getNameInfo(), CreateMethod->getType(), VK_PRValue);
+
+ auto *ImpCast = ImplicitCastExpr::Create(
+ AST, AST.getPointerType(CreateMethod->getType()),
+ CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());
+
+ CallExpr *InitExpr =
+ CallExpr::Create(AST, ImpCast, Args, ResourceTy, VK_PRValue,
+ SourceLocation(), FPOptionsOverride());
+ VD->setInit(InitExpr);
+ VD->setInitStyle(VarDecl::CallInit);
+ SemaRef.CheckCompleteVariableDeclaration(VD);
+ return true;
}
bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 8336bf00ed4cb..dd861b4b07cf8 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -34,7 +34,7 @@ RESOURCE Buffer;
#endif
-// CHECK: CXXRecordDecl {{.*}} implicit referenced <undeserialized declarations> class [[RESOURCE]] definition
+// CHECK: CXXRecordDecl {{.*}} implicit referenced class [[RESOURCE]] definition
// CHECK: FinalAttr {{.*}} Implicit final
// CHECK-NEXT: FieldDecl {{.*}} implicit __handle '__hlsl_resource_t
// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
diff --git a/clang/test/AST/HLSL/vk_binding_attr.hlsl b/clang/test/AST/HLSL/vk_binding_attr.hlsl
index 4cb2abdaef01a..d08165d7c593d 100644
--- a/clang/test/AST/HLSL/vk_binding_attr.hlsl
+++ b/clang/test/AST/HLSL/vk_binding_attr.hlsl
@@ -2,18 +2,23 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.8-library -finclude-default-header -ast-dump -o - %s | FileCheck %s -check-prefixes=DXIL,CHECK
// CHECK: VarDecl {{.*}} Buf 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
-// SPV-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer<float> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102
-// DXIL-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' 'void (unsigned int, int, unsigned int, unsigned int, const char *)'
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
-// DXIL-NEXT: IntegerLiteral {{.*}} 'int' 1
+// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
// SPV: HLSLVkBindingAttr {{.*}} 23 102
// DXIL-NOT: HLSLVkBindingAttr
[[vk::binding(23, 102)]] StructuredBuffer<float> Buf;
// CHECK: VarDecl {{.*}} Buf2 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer<float> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 14
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23
@@ -24,7 +29,10 @@
[[vk::binding(14, 1)]] StructuredBuffer<float> Buf2 : register(t23, space102);
// CHECK: VarDecl {{.*}} Buf3 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer<float> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 14
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23
@@ -43,28 +51,46 @@
}
// CHECK: VarDecl {{.*}} Buf4 'Buffer<int>':'hlsl::Buffer<int>'
-// SPV-NEXT: CXXConstructExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT: CallExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::Buffer<int> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
+// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 24
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 103
-// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' 'void (unsigned int, int, unsigned int, unsigned int, const char *)'
+// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
+// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
// SPV: HLSLVkBindingAttr {{.*}} 24 103
// DXIL-NOT: HLSLVkBindingAttr
[[vk::binding(24, 103)]] Buffer<int> Buf4;
// CHECK: VarDecl {{.*}} Buf5 'RWBuffer<int2>':'hlsl::RWBuffer<vector<int, 2>>'
-// SPV-NEXT: CXXConstructExpr {{.*}} 'RWBuffer<int2>':'hlsl::RWBuffer<vector<int, 2>>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT: CallExpr {{.*}} 'RWBuffer<int2>':'hlsl::RWBuffer<vector<int, 2>>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::RWBuffer<vector<int, 2>> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
+// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::RWBuffer<vector<int, 2>> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'Buffer<int2> (unsigned int, unsigned int, int, unsigned int, const char *)'
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 25
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 104
-// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' 'void (unsigned int, int, unsigned int, unsigned int, const char *)'
+// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::RWBuffer<vector<int, 2>> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer<int2> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
+// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
// SPV: HLSLVkBindingAttr {{.*}} 25 104
// DXIL-NOT: HLSLVkBindingAttr
[[vk::binding(25, 104)]] RWBuffer<int2> Buf5;
// CHECK: VarDecl {{.*}} Buf6 'RWStructuredBuffer<int>':'hlsl::RWStructuredBuffer<int>'
-// SPV-NEXT: CXXConstructExpr {{.*}} 'RWStructuredBuffer<int>':'hlsl::RWStructuredBuffer<int>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
+// CHECK-NEXT: CallExpr {{.*}} 'RWStructuredBuffer<int>':'hlsl::RWStructuredBuffer<int>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::RWStructuredBuffer<int> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
+// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 26
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 105
-// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' 'void (unsigned int, int, unsigned int, unsigned int, const char *)'
+// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 4
+// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
// SPV: HLSLVkBindingAttr {{.*}} 26 105
// DXIL-NOT: HLSLVkBindingAttr
[[vk::binding(26, 105)]] RWStructuredBuffer<int> Buf6;
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
index afda714106fac..c3d4fbb12a6f4 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
@@ -31,9 +31,11 @@ void SecondEntry() {}
// CHECK: ret void
-// Verify the constructor is alwaysinline
+// Verify the constructors are alwaysinline
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
-// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EjijjPKc({{.*}} [[CtorAttr:\#[0-9]+]]
+// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(ptr {{.*}} %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) {{.*}} [[CtorAttr:\#[0-9]+]]
+// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
+// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr {{.*}} %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) {{.*}} [[CtorAttr]]
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[InitAttr:\#[0-9]+]]
diff --git a/clang/test/CodeGenHLSL/debug/rwbuffer_debug_info.hlsl b/clang/test/CodeGenHLSL/debug/rwbuffer_debug_info.hlsl
index db0388e41eae9..941ab9b952685 100644
--- a/clang/test/CodeGenHLSL/debug/rwbuffer_debug_info.hlsl
+++ b/clang/test/CodeGenHLSL/debug/rwbuffer_debug_info.hlsl
@@ -1,11 +1,10 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s -debug-info-kind=standalone -dwarf-version=4 | FileCheck %s
-
// CHECK: [[DWTag:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "RWBuffer<float>",
+// CHECK: [[thisType:![0-9]+]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[DWTag]], size: 32)
// CHECK: [[RWBuffer:![0-9]+]] = distinct !DISubprogram(name: "RWBuffer",
// CHECK-SAME: scope: [[DWTag]]
-// CHECK: [[FirstThis:![0-9]+]] = !DILocalVariable(name: "this", arg: 1, scope: [[RWBuffer]], type: [[thisType:![0-9]+]]
-// CHECK: [[thisType]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[DWTag]], size: 32)
+// CHECK: [[FirstThis:![0-9]+]] = !DILocalVariable(name: "this", arg: 1, scope: [[RWBuffer]], type: [[thisType]]
RWBuffer<float> Out : register(u7, space4);
[numthreads(8,1,1)]
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
index 3a8d2c03e173c..35e1c14a0931f 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
@@ -28,29 +28,35 @@ export void foo() {
// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWByteAddressBuffer" poison, align 4
// CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1
-// Buf1 initialization part 1 - global init function that calls ByteAddressBuffer C1 constructor with explicit binding
+// Buf1 initialization part 1 - global init function that calls ByteAddressBuffer::__createFromBinding
// CHECK: define internal void @__cxx_global_var_init()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl17ByteAddressBufferC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf1,
+// CHECK-NEXT: call void @_ZN4hlsl17ByteAddressBuffer19__createFromBindingEjjijPKc(ptr {{.*}} @_ZL4Buf1,
// CHECK-SAME: i32 noundef 1, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
-// Buf1 initialization part 2 - body of ByteAddressBuffer C1 constructor with explicit binding that calls the C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl17ByteAddressBufferC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
-// CHECK: call void @_ZN4hlsl17ByteAddressBufferC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4)
-// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}})
+// Buf1 initialization part 2 - body of ByteAddressBuffer::__createFromBinding
+// CHECK: define {{.*}} void @_ZN4hlsl17ByteAddressBuffer19__createFromBindingEjjijPKc(
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::ByteAddressBuffer") align 4 %[[Tmp1:.*]], i32 noundef %registerNo,
+// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Handle1:.*]] = call target("dx.RawBuffer", i8, 0, 0)
+// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
+// CHECK: call void @_ZN4hlsl17ByteAddressBufferC1EU13_Res_t_Raw_CTDuu17__hlsl_resource_t(
+// CHECK-SAME: ptr {{.*}} %[[Tmp1]], target("dx.RawBuffer", i8, 0, 0) %[[Handle1]])
-// Buf2 initialization part 1 - global init function that calls RWByteAddressBuffer C1 constructor with implicit binding
+// Buf2 initialization part 1 - global init function that calls RWByteAddressBuffer::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl19RWByteAddressBufferC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf2,
-// CHECK-SAME: i32 noundef 0, i32 noundef 1, i32 noundef 0, i32 noundef 0, ptr noundef @[[Buf2Str]])
-
-// Buf2 initialization part 2 - body of RWByteAddressBuffer C1 constructor with implicit binding that calls the C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl19RWByteAddressBufferC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name)
-// CHECK: call void @_ZN4hlsl19RWByteAddressBufferC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this1,
-// CHECK-SAME: i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}})
+// CHECK-NEXT: call void @_ZN4hlsl19RWByteAddressBuffer27__createFromImplicitBindingEjjijPKc(ptr {{.*}} @_ZL4Buf2,
+// CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
+
+// Buf2 initialization part 2 - body of RWByteAddressBuffer::__createFromImplicitBinding
+// CHECK: define hidden void @_ZN4hlsl19RWByteAddressBuffer27__createFromImplicitBindingEjjijPKc(
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWByteAddressBuffer") align 4 %[[Tmp2:.*]], i32 noundef %orderId,
+// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Handle2:.*]] = call target("dx.RawBuffer", i8, 1, 0)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i8_1_0t(
+// CHECK: call void @_ZN4hlsl19RWByteAddressBufferC1EU13_Res_u_Raw_CTDuu17__hlsl_resource_t(
+// CHECK-SAME: ptr {{.*}} %[[Tmp2]], target("dx.RawBuffer", i8, 1, 0) %[[Handle2]])
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// RasterizerOrderedByteAddressBuffer C1 default constructor
@@ -65,23 +71,17 @@ export void foo() {
// CHECK: call void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}})
// CHECK-NEXT: ret void
-// Buf1 initialization part 3 - ByteAddressBuffer C2 constructor with explicit binding that initializes
-// handle with @llvm.dx.resource.handlefrombinding
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl17ByteAddressBufferC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
-// CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
-// CHECK-DXIL-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}})
-// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], ptr %__handle, align 4
-
-// Buf2 initialization part 3 - body of RWByteAddressBuffer C2 constructor with implicit binding that initializes
-// handle with @llvm.dx.resource.handlefromimplicitbinding
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl19RWByteAddressBufferC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name)
-// CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i8_1_0t
-// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}})
-// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %this1, i32 0, i32 0
-// CHECK-NEXT: store target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], ptr %__handle, align 4
+// Buf1 initialization part 3 - ByteAddressBuffer constructor constructor with handle
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl17ByteAddressBufferC2EU13_Res_t_Raw_CTDuu17__hlsl_resource_t(ptr {{.*}} %this,
+// CHECK-SAME: target("dx.RawBuffer", i8, 0, 0) %handle)
+// CHECK: %[[HandlePtr1:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %{{.*}}, ptr %[[HandlePtr1]], align 4
+
+// Buf2 initialization part 3 - body of RWByteAddressBuffer constructor with handle
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl19RWByteAddressBufferC1EU13_Res_u_Raw_CTDuu17__hlsl_resource_t(ptr {{.*}} %this,
+// CHECK-SAME: target("dx.RawBuffer", i8, 1, 0) %handle)
+// CHECK: %[[HandlePtr2:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 0) %{{.*}}, ptr %[[HandlePtr2]], align 4
// Buf3 initialization part 3 - body of RasterizerOrderedByteAddressBuffer default C2 constructor that
// initializes handle to poison
diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
index 114468914e2ea..c5c40449c6c8e 100644
--- a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
@@ -28,60 +28,60 @@ export void foo() {
// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWBuffer.0" poison, align 4
// CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1
-// Buf1 initialization part 1 - global init function that calls RWBuffer<float> C1 constructor with explicit binding
+// Buf1 initialization part 1 - global init function that calls RWBuffer<float>::__createFromBinding
// CHECK: define internal void @__cxx_global_var_init()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf1,
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 @_ZL4Buf1,
// CHECK-SAME: i32 noundef 5, i32 noundef 3, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
-// Buf1 initialization part 2 - body of RWBuffer<float> C1 constructor with explicit binding that calls the C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
-// CHECK: call void @_ZN4hlsl8RWBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4)
-// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}})
+// Buf1 initialization part 2 - body of RWBuffer<float>::__createFromBinding
+// CHECK: define {{.*}} void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp1:.*]], i32 noundef %registerNo,
+// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Handle1:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0)
+// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(
+// CHECK: call void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(
+// CHECK-SAME: ptr {{.*}} %[[Tmp1]], target("dx.TypedBuffer", float, 1, 0, 0) %[[Handle1]])
-// Buf2 initialization part 1 - global init function that calls RWBuffer<float> C1 constructor with implicit binding
+// Buf2 initialization part 1 - global init function that RWBuffer<float>::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf2,
-// CHECK-SAME: i32 noundef 0, i32 noundef 1, i32 noundef 0, i32 noundef 0, ptr noundef @[[Buf2Str]])
-
-// Buf2 initialization part 2 - body of RWBuffer<float> C1 constructor with implicit binding that calls the C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name)
-// CHECK: call void @_ZN4hlsl8RWBufferIdEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4)
-// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}})
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} @_ZL4Buf2,
+// CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
+
+// Buf2 initialization part 2 - body of RWBuffer<float>::__createFromImplicitBinding call
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp2:.*]], i32 noundef %orderId,
+// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Handle2:.*]] = call target("dx.TypedBuffer", double, 1, 0, 0)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_1_0_0t(
+// CHECK: call void @_ZN4hlsl8RWBufferIdEC1EU9_Res_u_CTdu17__hlsl_resource_t(
+// CHECK-SAME: ptr {{.*}} %[[Tmp2]], target("dx.TypedBuffer", double, 1, 0, 0) %[[Handle2]])
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by RWBuffer<int> C1 default constructor
// CHECK: define void @_Z3foov()
// CHECK-NEXT: entry:
// CHECK-NEXT: %Buf3 = alloca %"class.hlsl::RWBuffer.1", align 4
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %Buf3)
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1Ev(ptr {{.*}} %Buf3)
// Buf3 initialization part 2 - body of RWBuffer<int> default C1 constructor that calls the default C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
-// CHECK: call void @_ZN4hlsl8RWBufferIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}})
-
-// Buf1 initialization part 3 - body of RWBuffer<float> C2 constructor with explicit binding that initializes
-// handle with @llvm.dx.resource.handlefrombinding
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
-// CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(
-// CHECK-DXIL-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}})
-// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %[[HANDLE]], ptr %__handle, align 4
-
-// Buf2 initialization part 3 - body of RWBuffer<float> C2 constructor with implicit binding that initializes
-// handle with @llvm.dx.resource.handlefromimplicitbinding
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name)
-// CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", double, 1, 0, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_1_0_0t
-// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}})
-// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %{{.*}}, i32 0, i32 0
-// CHECK-NEXT: store target("dx.TypedBuffer", double, 1, 0, 0) %[[HANDLE]], ptr %__handle, align 4
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC1Ev(ptr {{.*}} %this)
+// CHECK: call void @_ZN4hlsl8RWBufferIiEC2Ev(ptr {{.*}} %{{.*}})
+
+// Buf1 initialization part 3 - body of RWBuffer<float> constructor with handle
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr {{.*}} %this,
+// CHECK-SAME: target("dx.TypedBuffer", float, 1, 0, 0) %handle)
+// CHECK: %[[HandlePtr1:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %{{.*}}, ptr %[[HandlePtr1]], align 4
+
+// Buf2 initialization part 3 - body of RWBuffer<double> constructor with handle
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdEC1EU9_Res_u_CTdu17__hlsl_resource_t(ptr {{.*}} %this,
+// CHECK-SAME: target("dx.TypedBuffer", double, 1, 0, 0) %handle)
+// CHECK: %[[HandlePtr2:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %{{.*}}, i32 0, i32 0
+// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", double, 1, 0, 0) %{{.*}}, ptr %[[HandlePtr2]], align 4
// Buf3 initialization part 3 - body of RWBuffer<int> default C2 constructor that initializes handle to poison
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC2Ev(ptr {{.*}} %this)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.1", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: store target("dx.TypedBuffer", i32, 1, 0, 1) poison, ptr %__handle, align 4
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
index 28841732df99e..834a9639484a5 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
@@ -27,32 +27,37 @@ export void foo() {
// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
// CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1
-// Buf1 initialization part 1 - global init function that calls StructuredBuffer<float> C1 constructor
+// Buf1 initialization part 1 - global init function that calls StructuredBuffer<float>::__createFromBinding
// with explicit binding
// CHECK: define internal void @__cxx_global_var_init()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl16StructuredBufferIfEC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf1,
+// CHECK-NEXT: call void @_ZN4hlsl16StructuredBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} @_ZL4Buf1,
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
-// Buf1 initialization part 2 - body of StructuredBuffer<float> C1 constructor with explicit binding
-// that calls the C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl16StructuredBufferIfEC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
-// CHECK: call void @_ZN4hlsl16StructuredBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4)
-// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}})
+// Buf1 initialization part 2 - body of StructuredBuffer<float>::::__createFromBinding
-// Buf2 initialization part 1 - global init function that calls RWStructuredBuffer<float> C1 constructor with
-// implicit binding
+// CHECK: define {{.*}} void @_ZN4hlsl16StructuredBufferIfE19__createFromBindingEjjijPKc(
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::StructuredBuffer") align 4 %[[Tmp1:.*]], i32 noundef %registerNo,
+// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Handle1:.*]] = call target("dx.RawBuffer", float, 0, 0)
+// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(
+// CHECK: call void @_ZN4hlsl16StructuredBufferIfEC1EU13_Res_t_Raw_CTfu17__hlsl_resource_t(
+// CHECK-SAME: ptr {{.*}} %[[Tmp1]], target("dx.RawBuffer", float, 0, 0) %[[Handle1]])
+
+// Buf2 initialization part 1 - global init function that calls RWStructuredBuffer<float>::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl18RWStructuredBufferIfEC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf2,
-// CHECK-SAME: i32 noundef 0, i32 noundef 1, i32 noundef 0, i32 noundef 0, ptr noundef @[[Buf2Str]])
-
-// Buf2 initialization part 2 - body of RWStructuredBuffer<float> C1 constructor with implicit binding that calls the C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfEC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name)
-// CHECK: call void @_ZN4hlsl18RWStructuredBufferIfEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4)
-// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}})
+// CHECK-NEXT: call void @_ZN4hlsl18RWStructuredBufferIfE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} @_ZL4Buf2,
+// CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
+
+// Buf2 initialization part 2 - body of RWStructuredBuffer<float>::__createFromImplicitBinding
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfE27__createFromImplicitBindingEjjijPKc(
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWStructuredBuffer") align 4 %[[Tmp2:.*]], i32 noundef %orderId,
+// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Handle2:.*]] = call target("dx.RawBuffer", float, 1, 0)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f32_1_0t(
+// CHECK: call void @_ZN4hlsl18RWStructuredBufferIfEC1EU13_Res_u_Raw_CTfu17__hlsl_resource_t(
+// CHECK-SAME: ptr {{.*}} %[[Tmp2]], target("dx.RawBuffer", float, 1, 0) %[[Handle2]])
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// AppendStructuredBuffer<float> C1 default constructor
@@ -66,23 +71,17 @@ export void foo() {
// CHECK: define linkonce_odr hidden void @_ZN4hlsl22AppendStructuredBufferIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
// CHECK: call void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}})
-// Buf1 initialization part 3 - body of AppendStructuredBuffer<float> C2 constructor with explicit binding
-// that initializes handle with @llvm.dx.resource.handlefrombinding
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl16StructuredBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
-// CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(
-// CHECK-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}})
-// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], ptr %__handle, align 4
-
-// Buf2 initialization part 3 - body of RWStructuredBuffer<float> C2 constructor with implicit binding that initializes
-// handle with @llvm.dx.resource.handlefromimplicitbinding
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this,
-// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name)
-// CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f32_1_0t
-// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}})
-// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-NEXT: store target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], ptr %__handle, align 4
+// Buf1 initialization part 3 - body of StructuredBuffer<float> constructor with handle
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl16StructuredBufferIfEC1EU13_Res_t_Raw_CTfu17__hlsl_resource_t(ptr {{.*}} %this,
+// CHECK-SAME: target("dx.RawBuffer", float, 0, 0) %handle)
+// CHECK: %[[HandlePtr1:.*]] = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %{{.*}}, ptr %[[HandlePtr1]], align 4
+
+// Buf2 initialization part 3 - body of RWStructuredBuffer<float> constructor with handle
+// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfEC2EU13_Res_u_Raw_CTfu17__hlsl_resource_t(ptr {{.*}} %this,
+// CHECK-SAME: target("dx.RawBuffer", float, 1, 0) %handle)
+// CHECK: %[[HandlePtr2:.*]] = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %{{.*}}, ptr %[[HandlePtr2]], align 4
// Buf3 initialization part 3 - body of AppendStructuredBuffer<float> default C2 constructor that
// initializes handle to poison
diff --git a/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl b/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl
index 2a6e51d765bd1..8884e391ec917 100644
--- a/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl
+++ b/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl
@@ -12,32 +12,20 @@
// CHECK: @_ZL4T3S0 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
// CHECK: @_ZL5Array = internal global [10 x %"class.hlsl::RWBuffer.1"] poison, align 4
-// CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+// CHECK: call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_1_0_0t(
-// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i1 false, ptr %{{.*}})
-// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0
-// CHECK: store target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4
RWBuffer<float4> U0S0 : register(u0);
-// CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0)
+// CHECK: call target("dx.TypedBuffer", float, 1, 0, 0)
// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(
-// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i1 false, ptr %{{.*}})
-// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %this{{[0-9]*}}, i32 0, i32 0
-// CHECK: store target("dx.TypedBuffer", float, 1, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4
RWBuffer<float> U5S3 : register(u5, space3);
-// CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", i32, 0, 0)
+// CHECK: call target("dx.RawBuffer", i32, 0, 0)
// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(
-// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i1 false, ptr %{{.*}})
-// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0
-// CHECK: store target("dx.RawBuffer", i32, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4
StructuredBuffer<int> T2S2 : register(t2, space2);
-// CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", %struct.S, 1, 0)
+// CHECK: call target("dx.RawBuffer", %struct.S, 1, 0)
// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_s_struct.Ss_1_0t(
-// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i1 false, ptr %{{.*}})
-// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0
-// CHECK: store target("dx.RawBuffer", %struct.S, 1, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4
struct S {
float4 f;
int i;
diff --git a/clang/test/CodeGenHLSL/static-local-ctor.hlsl b/clang/test/CodeGenHLSL/static-local-ctor.hlsl
index 9a4bf66f030ed..f44d70dff7811 100644
--- a/clang/test/CodeGenHLSL/static-local-ctor.hlsl
+++ b/clang/test/CodeGenHLSL/static-local-ctor.hlsl
@@ -22,7 +22,7 @@ void InitBuf(RWBuffer<int> buf) {
// CHECK-NEXT: br i1 [[Tmp3]]
// CHECK-NOT: _Init_thread_header
// CHECK: init.check:
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiE27__createFromImplicitBindingEjjijPKc(
// CHECK-NEXT: store i8 1, ptr @_ZGVZ4mainvE5mybuf
// CHECK-NOT: _Init_thread_footer
diff --git a/out.ll b/out.ll
new file mode 100644
index 0000000000000..81469245d028e
--- /dev/null
+++ b/out.ll
@@ -0,0 +1,251 @@
+; ModuleID = 'C:\llvm-project\clang\test\CodeGenHLSL\debug\rwbuffer_debug_info.hlsl'
+source_filename = "C:\\llvm-project\\clang\\test\\CodeGenHLSL\\debug\\rwbuffer_debug_info.hlsl"
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.6-pc-shadermodel6.6-compute"
+
+%"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", float, 1, 0, 0) }
+
+ at _ZL3Out = internal global %"class.hlsl::RWBuffer" poison, align 4, !dbg !0
+ at .str = private unnamed_addr constant [4 x i8] c"Out\00", align 1
+
+; Function Attrs: alwaysinline convergent nounwind
+define internal void @__cxx_global_var_init() #0 !dbg !56 {
+entry:
+ call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr dead_on_unwind writable sret(%"class.hlsl::RWBuffer") align 4 @_ZL3Out, i32 noundef 7, i32 noundef 4, i32 noundef 1, i32 noundef 0, ptr noundef @.str) #5, !dbg !59
+ ret void, !dbg !59
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr dead_on_unwind noalias writable sret(%"class.hlsl::RWBuffer") align 4 %agg.result, i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) #1 align 2 !dbg !60 {
+entry:
+ %registerNo.addr = alloca i32, align 4
+ %spaceNo.addr = alloca i32, align 4
+ %range.addr = alloca i32, align 4
+ %index.addr = alloca i32, align 4
+ %name.addr = alloca ptr, align 4
+ %tmp = alloca target("dx.TypedBuffer", float, 1, 0, 0), align 4
+ store i32 %registerNo, ptr %registerNo.addr, align 4
+ #dbg_declare(ptr %registerNo.addr, !62, !DIExpression(), !63)
+ store i32 %spaceNo, ptr %spaceNo.addr, align 4
+ #dbg_declare(ptr %spaceNo.addr, !64, !DIExpression(), !63)
+ store i32 %range, ptr %range.addr, align 4
+ #dbg_declare(ptr %range.addr, !65, !DIExpression(), !63)
+ store i32 %index, ptr %index.addr, align 4
+ #dbg_declare(ptr %index.addr, !66, !DIExpression(), !63)
+ store ptr %name, ptr %name.addr, align 4
+ #dbg_declare(ptr %name.addr, !67, !DIExpression(), !63)
+ #dbg_declare(ptr %tmp, !68, !DIExpression(), !63)
+ %0 = load i32, ptr %registerNo.addr, align 4, !dbg !69
+ %1 = load i32, ptr %spaceNo.addr, align 4, !dbg !69
+ %2 = load i32, ptr %range.addr, align 4, !dbg !69
+ %3 = load i32, ptr %index.addr, align 4, !dbg !69
+ %4 = load ptr, ptr %name.addr, align 4, !dbg !69
+ %5 = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 %1, i32 %0, i32 %2, i32 %3, i1 false, ptr %4), !dbg !69
+ call void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(ptr noundef nonnull align 4 dereferenceable(4) %agg.result, target("dx.TypedBuffer", float, 1, 0, 0) %5) #5, !dbg !69
+ ret void, !dbg !70
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define internal void @_Z4maini(i32 noundef %GI) #1 !dbg !71 {
+entry:
+ %GI.addr = alloca i32, align 4
+ store i32 %GI, ptr %GI.addr, align 4
+ #dbg_declare(ptr %GI.addr, !74, !DIExpression(), !75)
+ %0 = load i32, ptr %GI.addr, align 4, !dbg !76
+ %call = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl8RWBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(4) @_ZL3Out, i32 noundef %0) #5, !dbg !77
+ store float 0.000000e+00, ptr %call, align 4, !dbg !78
+ ret void, !dbg !79
+}
+
+; Function Attrs: convergent noinline norecurse optnone
+define void @main() #2 {
+entry:
+ call void @_GLOBAL__sub_I_rwbuffer_debug_info.hlsl()
+ %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+ call void @_Z4maini(i32 %0)
+ ret void
+}
+
+; Function Attrs: nounwind willreturn memory(none)
+declare i32 @llvm.dx.flattened.thread.id.in.group() #3
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define linkonce_odr hidden noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl8RWBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(4) %this, i32 noundef %Index) #1 align 2 !dbg !80 {
+entry:
+ %this.addr = alloca ptr, align 4
+ %Index.addr = alloca i32, align 4
+ store ptr %this, ptr %this.addr, align 4
+ #dbg_declare(ptr %this.addr, !81, !DIExpression(), !83)
+ store i32 %Index, ptr %Index.addr, align 4
+ #dbg_declare(ptr %Index.addr, !84, !DIExpression(), !85)
+ %this1 = load ptr, ptr %this.addr, align 4
+ %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %this1, i32 0, i32 0, !dbg !83
+ %0 = load target("dx.TypedBuffer", float, 1, 0, 0), ptr %__handle, align 4, !dbg !83
+ %1 = load i32, ptr %Index.addr, align 4, !dbg !83
+ %2 = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %0, i32 %1), !dbg !83
+ ret ptr %2, !dbg !86
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32, i32, i32, i32, i1, ptr) #4
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(ptr noundef nonnull align 4 dereferenceable(4) %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) unnamed_addr #1 align 2 !dbg !87 {
+entry:
+ %this.addr = alloca ptr, align 4
+ %handle.addr = alloca target("dx.TypedBuffer", float, 1, 0, 0), align 4
+ store ptr %this, ptr %this.addr, align 4
+ #dbg_declare(ptr %this.addr, !88, !DIExpression(), !89)
+ store target("dx.TypedBuffer", float, 1, 0, 0) %handle, ptr %handle.addr, align 4
+ #dbg_declare(ptr %handle.addr, !90, !DIExpression(), !91)
+ %this1 = load ptr, ptr %this.addr, align 4
+ %0 = load target("dx.TypedBuffer", float, 1, 0, 0), ptr %handle.addr, align 4, !dbg !92
+ call void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr noundef nonnull align 4 dereferenceable(4) %this1, target("dx.TypedBuffer", float, 1, 0, 0) %0) #5, !dbg !92
+ ret void, !dbg !93
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr noundef nonnull align 4 dereferenceable(4) %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) unnamed_addr #1 align 2 !dbg !95 {
+entry:
+ %this.addr = alloca ptr, align 4
+ %handle.addr = alloca target("dx.TypedBuffer", float, 1, 0, 0), align 4
+ store ptr %this, ptr %this.addr, align 4
+ #dbg_declare(ptr %this.addr, !96, !DIExpression(), !97)
+ store target("dx.TypedBuffer", float, 1, 0, 0) %handle, ptr %handle.addr, align 4
+ #dbg_declare(ptr %handle.addr, !98, !DIExpression(), !99)
+ %this1 = load ptr, ptr %this.addr, align 4
+ %0 = load target("dx.TypedBuffer", float, 1, 0, 0), ptr %handle.addr, align 4, !dbg !100
+ %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %this1, i32 0, i32 0, !dbg !100
+ store target("dx.TypedBuffer", float, 1, 0, 0) %0, ptr %__handle, align 4, !dbg !100
+ ret void, !dbg !102
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #4
+
+; Function Attrs: alwaysinline convergent nounwind
+define internal void @_GLOBAL__sub_I_rwbuffer_debug_info.hlsl() #0 !dbg !104 {
+entry:
+ call void @__cxx_global_var_init(), !dbg !106
+ ret void
+}
+
+attributes #0 = { alwaysinline convergent nounwind "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { alwaysinline convergent mustprogress norecurse nounwind "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #2 = { convergent noinline norecurse optnone "approx-func-fp-math"="true" "hlsl.numthreads"="8,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #3 = { nounwind willreturn memory(none) }
+attributes #4 = { nocallback nofree nosync nounwind willreturn memory(none) }
+attributes #5 = { convergent }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!51, !52, !53}
+!dx.valver = !{!54}
+!llvm.ident = !{!55}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "Out", linkageName: "_ZL3Out", scope: !2, file: !5, line: 9, type: !6, isLocal: true, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_11, file: !3, producer: "clang version 22.0.0git (C:/llvm-project/clang e5cfb97d26f63942eea3c9353680fa4e669b02e7)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "C:\\llvm-project\\clang\\test\\CodeGenHLSL\\debug\\<stdin>", directory: "")
+!4 = !{!0}
+!5 = !DIFile(filename: "C:\\llvm-project\\clang\\test\\CodeGenHLSL\\debug\\rwbuffer_debug_info.hlsl", directory: "")
+!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "RWBuffer<float>", scope: !7, size: 32, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !8, templateParams: !49, identifier: "_ZTSN4hlsl8RWBufferIfEE")
+!7 = !DINamespace(name: "hlsl", scope: null)
+!8 = !{!9, !12, !16, !19, !27, !28, !31, !34, !42, !46}
+!9 = !DIDerivedType(tag: DW_TAG_member, name: "__handle", scope: !6, file: !3, line: 9, baseType: !10, size: 32)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32)
+!11 = !DICompositeType(tag: DW_TAG_structure_type, name: "__hlsl_resource_t", file: !3, flags: DIFlagFwdDecl)
+!12 = !DISubprogram(name: "RWBuffer", scope: !6, file: !3, type: !13, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
+!13 = !DISubroutineType(types: !14)
+!14 = !{null, !15}
+!15 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !6, size: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
+!16 = !DISubprogram(name: "RWBuffer", scope: !6, file: !3, type: !17, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
+!17 = !DISubroutineType(types: !18)
+!18 = !{null, !15, !10}
+!19 = !DISubprogram(name: "__createFromBinding", linkageName: "_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc", scope: !6, file: !3, type: !20, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0)
+!20 = !DISubroutineType(types: !21)
+!21 = !{!6, !22, !22, !23, !22, !24}
+!22 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!23 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!24 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !25, size: 32)
+!25 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !26)
+!26 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!27 = !DISubprogram(name: "__createFromImplicitBinding", linkageName: "_ZN4hlsl8RWBufferIfE27__createFromImplicitBindingEjjijPKc", scope: !6, file: !3, type: !20, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0)
+!28 = !DISubprogram(name: "RWBuffer", scope: !6, file: !3, type: !29, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
+!29 = !DISubroutineType(types: !30)
+!30 = !{null, !15, !22, !22, !23, !22, !24}
+!31 = !DISubprogram(name: "RWBuffer", scope: !6, file: !3, type: !32, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
+!32 = !DISubroutineType(types: !33)
+!33 = !{null, !15, !22, !23, !22, !22, !24}
+!34 = !DISubprogram(name: "operator[]", linkageName: "_ZNK4hlsl8RWBufferIfEixEj", scope: !6, file: !3, type: !35, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
+!35 = !DISubroutineType(types: !36)
+!36 = !{!37, !40, !22}
+!37 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !38, size: 32)
+!38 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !39)
+!39 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!40 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !41, size: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
+!41 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !6)
+!42 = !DISubprogram(name: "operator[]", linkageName: "_ZN4hlsl8RWBufferIfEixEj", scope: !6, file: !3, type: !43, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
+!43 = !DISubroutineType(types: !44)
+!44 = !{!45, !15, !22}
+!45 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !39, size: 32)
+!46 = !DISubprogram(name: "Load", linkageName: "_ZN4hlsl8RWBufferIfE4LoadEj", scope: !6, file: !3, type: !47, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
+!47 = !DISubroutineType(types: !48)
+!48 = !{!39, !15, !22}
+!49 = !{!50}
+!50 = !DITemplateTypeParameter(name: "element_type", type: !39)
+!51 = !{i32 7, !"Dwarf Version", i32 4}
+!52 = !{i32 2, !"Debug Info Version", i32 3}
+!53 = !{i32 1, !"wchar_size", i32 4}
+!54 = !{i32 1, i32 8}
+!55 = !{!"clang version 22.0.0git (C:/llvm-project/clang e5cfb97d26f63942eea3c9353680fa4e669b02e7)"}
+!56 = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !3, file: !3, type: !57, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2)
+!57 = !DISubroutineType(types: !58)
+!58 = !{null}
+!59 = !DILocation(line: 0, scope: !56)
+!60 = distinct !DISubprogram(name: "__createFromBinding", linkageName: "_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc", scope: !6, file: !3, line: 14, type: !20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !19, retainedNodes: !61)
+!61 = !{}
+!62 = !DILocalVariable(name: "registerNo", arg: 1, scope: !60, file: !3, type: !22)
+!63 = !DILocation(line: 0, column: 1, scope: !60)
+!64 = !DILocalVariable(name: "spaceNo", arg: 2, scope: !60, file: !3, type: !22)
+!65 = !DILocalVariable(name: "range", arg: 3, scope: !60, file: !3, type: !23)
+!66 = !DILocalVariable(name: "index", arg: 4, scope: !60, file: !3, type: !22)
+!67 = !DILocalVariable(name: "name", arg: 5, scope: !60, file: !3, type: !24)
+!68 = !DILocalVariable(name: "tmp", scope: !60, file: !3, type: !10)
+!69 = !DILocation(line: 0, scope: !60)
+!70 = !DILocation(line: 14, column: 1, scope: !60)
+!71 = distinct !DISubprogram(name: "main", linkageName: "_Z4maini", scope: !5, file: !5, line: 12, type: !72, scopeLine: 12, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !61)
+!72 = !DISubroutineType(types: !73)
+!73 = !{null, !23}
+!74 = !DILocalVariable(name: "GI", arg: 1, scope: !71, file: !5, line: 12, type: !23)
+!75 = !DILocation(line: 12, column: 15, scope: !71)
+!76 = !DILocation(line: 13, column: 7, scope: !71)
+!77 = !DILocation(line: 13, column: 3, scope: !71)
+!78 = !DILocation(line: 13, column: 11, scope: !71)
+!79 = !DILocation(line: 14, column: 1, scope: !71)
+!80 = distinct !DISubprogram(name: "operator[]", linkageName: "_ZN4hlsl8RWBufferIfEixEj", scope: !6, file: !3, line: 14, type: !43, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !42, retainedNodes: !61)
+!81 = !DILocalVariable(name: "this", arg: 1, scope: !80, type: !82, flags: DIFlagArtificial | DIFlagObjectPointer)
+!82 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !6, size: 32)
+!83 = !DILocation(line: 0, scope: !80)
+!84 = !DILocalVariable(name: "Index", arg: 2, scope: !80, file: !3, type: !22)
+!85 = !DILocation(line: 0, column: 1, scope: !80)
+!86 = !DILocation(line: 14, column: 1, scope: !80)
+!87 = distinct !DISubprogram(name: "RWBuffer", linkageName: "_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t", scope: !6, file: !3, line: 14, type: !17, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !16, retainedNodes: !61)
+!88 = !DILocalVariable(name: "this", arg: 1, scope: !87, type: !82, flags: DIFlagArtificial | DIFlagObjectPointer)
+!89 = !DILocation(line: 0, scope: !87)
+!90 = !DILocalVariable(name: "handle", arg: 2, scope: !87, file: !3, type: !10)
+!91 = !DILocation(line: 0, column: 1, scope: !87)
+!92 = !DILocation(line: 14, column: 1, scope: !87)
+!93 = !DILocation(line: 14, column: 1, scope: !94)
+!94 = !DILexicalBlockFile(scope: !87, file: !5, discriminator: 0)
+!95 = distinct !DISubprogram(name: "RWBuffer", linkageName: "_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t", scope: !6, file: !3, line: 14, type: !17, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !16, retainedNodes: !61)
+!96 = !DILocalVariable(name: "this", arg: 1, scope: !95, type: !82, flags: DIFlagArtificial | DIFlagObjectPointer)
+!97 = !DILocation(line: 0, scope: !95)
+!98 = !DILocalVariable(name: "handle", arg: 2, scope: !95, file: !3, type: !10)
+!99 = !DILocation(line: 0, column: 1, scope: !95)
+!100 = !DILocation(line: 0, scope: !101)
+!101 = distinct !DILexicalBlock(scope: !95, file: !5, line: 14, column: 1)
+!102 = !DILocation(line: 14, column: 1, scope: !103)
+!103 = !DILexicalBlockFile(scope: !95, file: !5, discriminator: 0)
+!104 = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_rwbuffer_debug_info.hlsl", scope: !3, file: !3, type: !105, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2)
+!105 = !DISubroutineType(types: !61)
+!106 = !DILocation(line: 0, scope: !104)
>From b13a530c46348a6f8e2c2d770209ffa93ebb1125 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 2 Sep 2025 17:45:00 -0700
Subject: [PATCH 04/12] cleanup
---
out.ll | 251 ---------------------------------------------------------
1 file changed, 251 deletions(-)
delete mode 100644 out.ll
diff --git a/out.ll b/out.ll
deleted file mode 100644
index 81469245d028e..0000000000000
--- a/out.ll
+++ /dev/null
@@ -1,251 +0,0 @@
-; ModuleID = 'C:\llvm-project\clang\test\CodeGenHLSL\debug\rwbuffer_debug_info.hlsl'
-source_filename = "C:\\llvm-project\\clang\\test\\CodeGenHLSL\\debug\\rwbuffer_debug_info.hlsl"
-target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
-target triple = "dxilv1.6-pc-shadermodel6.6-compute"
-
-%"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", float, 1, 0, 0) }
-
- at _ZL3Out = internal global %"class.hlsl::RWBuffer" poison, align 4, !dbg !0
- at .str = private unnamed_addr constant [4 x i8] c"Out\00", align 1
-
-; Function Attrs: alwaysinline convergent nounwind
-define internal void @__cxx_global_var_init() #0 !dbg !56 {
-entry:
- call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr dead_on_unwind writable sret(%"class.hlsl::RWBuffer") align 4 @_ZL3Out, i32 noundef 7, i32 noundef 4, i32 noundef 1, i32 noundef 0, ptr noundef @.str) #5, !dbg !59
- ret void, !dbg !59
-}
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr dead_on_unwind noalias writable sret(%"class.hlsl::RWBuffer") align 4 %agg.result, i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) #1 align 2 !dbg !60 {
-entry:
- %registerNo.addr = alloca i32, align 4
- %spaceNo.addr = alloca i32, align 4
- %range.addr = alloca i32, align 4
- %index.addr = alloca i32, align 4
- %name.addr = alloca ptr, align 4
- %tmp = alloca target("dx.TypedBuffer", float, 1, 0, 0), align 4
- store i32 %registerNo, ptr %registerNo.addr, align 4
- #dbg_declare(ptr %registerNo.addr, !62, !DIExpression(), !63)
- store i32 %spaceNo, ptr %spaceNo.addr, align 4
- #dbg_declare(ptr %spaceNo.addr, !64, !DIExpression(), !63)
- store i32 %range, ptr %range.addr, align 4
- #dbg_declare(ptr %range.addr, !65, !DIExpression(), !63)
- store i32 %index, ptr %index.addr, align 4
- #dbg_declare(ptr %index.addr, !66, !DIExpression(), !63)
- store ptr %name, ptr %name.addr, align 4
- #dbg_declare(ptr %name.addr, !67, !DIExpression(), !63)
- #dbg_declare(ptr %tmp, !68, !DIExpression(), !63)
- %0 = load i32, ptr %registerNo.addr, align 4, !dbg !69
- %1 = load i32, ptr %spaceNo.addr, align 4, !dbg !69
- %2 = load i32, ptr %range.addr, align 4, !dbg !69
- %3 = load i32, ptr %index.addr, align 4, !dbg !69
- %4 = load ptr, ptr %name.addr, align 4, !dbg !69
- %5 = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 %1, i32 %0, i32 %2, i32 %3, i1 false, ptr %4), !dbg !69
- call void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(ptr noundef nonnull align 4 dereferenceable(4) %agg.result, target("dx.TypedBuffer", float, 1, 0, 0) %5) #5, !dbg !69
- ret void, !dbg !70
-}
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define internal void @_Z4maini(i32 noundef %GI) #1 !dbg !71 {
-entry:
- %GI.addr = alloca i32, align 4
- store i32 %GI, ptr %GI.addr, align 4
- #dbg_declare(ptr %GI.addr, !74, !DIExpression(), !75)
- %0 = load i32, ptr %GI.addr, align 4, !dbg !76
- %call = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl8RWBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(4) @_ZL3Out, i32 noundef %0) #5, !dbg !77
- store float 0.000000e+00, ptr %call, align 4, !dbg !78
- ret void, !dbg !79
-}
-
-; Function Attrs: convergent noinline norecurse optnone
-define void @main() #2 {
-entry:
- call void @_GLOBAL__sub_I_rwbuffer_debug_info.hlsl()
- %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
- call void @_Z4maini(i32 %0)
- ret void
-}
-
-; Function Attrs: nounwind willreturn memory(none)
-declare i32 @llvm.dx.flattened.thread.id.in.group() #3
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define linkonce_odr hidden noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl8RWBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(4) %this, i32 noundef %Index) #1 align 2 !dbg !80 {
-entry:
- %this.addr = alloca ptr, align 4
- %Index.addr = alloca i32, align 4
- store ptr %this, ptr %this.addr, align 4
- #dbg_declare(ptr %this.addr, !81, !DIExpression(), !83)
- store i32 %Index, ptr %Index.addr, align 4
- #dbg_declare(ptr %Index.addr, !84, !DIExpression(), !85)
- %this1 = load ptr, ptr %this.addr, align 4
- %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %this1, i32 0, i32 0, !dbg !83
- %0 = load target("dx.TypedBuffer", float, 1, 0, 0), ptr %__handle, align 4, !dbg !83
- %1 = load i32, ptr %Index.addr, align 4, !dbg !83
- %2 = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %0, i32 %1), !dbg !83
- ret ptr %2, !dbg !86
-}
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32, i32, i32, i32, i1, ptr) #4
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(ptr noundef nonnull align 4 dereferenceable(4) %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) unnamed_addr #1 align 2 !dbg !87 {
-entry:
- %this.addr = alloca ptr, align 4
- %handle.addr = alloca target("dx.TypedBuffer", float, 1, 0, 0), align 4
- store ptr %this, ptr %this.addr, align 4
- #dbg_declare(ptr %this.addr, !88, !DIExpression(), !89)
- store target("dx.TypedBuffer", float, 1, 0, 0) %handle, ptr %handle.addr, align 4
- #dbg_declare(ptr %handle.addr, !90, !DIExpression(), !91)
- %this1 = load ptr, ptr %this.addr, align 4
- %0 = load target("dx.TypedBuffer", float, 1, 0, 0), ptr %handle.addr, align 4, !dbg !92
- call void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr noundef nonnull align 4 dereferenceable(4) %this1, target("dx.TypedBuffer", float, 1, 0, 0) %0) #5, !dbg !92
- ret void, !dbg !93
-}
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr noundef nonnull align 4 dereferenceable(4) %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) unnamed_addr #1 align 2 !dbg !95 {
-entry:
- %this.addr = alloca ptr, align 4
- %handle.addr = alloca target("dx.TypedBuffer", float, 1, 0, 0), align 4
- store ptr %this, ptr %this.addr, align 4
- #dbg_declare(ptr %this.addr, !96, !DIExpression(), !97)
- store target("dx.TypedBuffer", float, 1, 0, 0) %handle, ptr %handle.addr, align 4
- #dbg_declare(ptr %handle.addr, !98, !DIExpression(), !99)
- %this1 = load ptr, ptr %this.addr, align 4
- %0 = load target("dx.TypedBuffer", float, 1, 0, 0), ptr %handle.addr, align 4, !dbg !100
- %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %this1, i32 0, i32 0, !dbg !100
- store target("dx.TypedBuffer", float, 1, 0, 0) %0, ptr %__handle, align 4, !dbg !100
- ret void, !dbg !102
-}
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
-declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #4
-
-; Function Attrs: alwaysinline convergent nounwind
-define internal void @_GLOBAL__sub_I_rwbuffer_debug_info.hlsl() #0 !dbg !104 {
-entry:
- call void @__cxx_global_var_init(), !dbg !106
- ret void
-}
-
-attributes #0 = { alwaysinline convergent nounwind "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-attributes #1 = { alwaysinline convergent mustprogress norecurse nounwind "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-attributes #2 = { convergent noinline norecurse optnone "approx-func-fp-math"="true" "hlsl.numthreads"="8,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-attributes #3 = { nounwind willreturn memory(none) }
-attributes #4 = { nocallback nofree nosync nounwind willreturn memory(none) }
-attributes #5 = { convergent }
-
-!llvm.dbg.cu = !{!2}
-!llvm.module.flags = !{!51, !52, !53}
-!dx.valver = !{!54}
-!llvm.ident = !{!55}
-
-!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
-!1 = distinct !DIGlobalVariable(name: "Out", linkageName: "_ZL3Out", scope: !2, file: !5, line: 9, type: !6, isLocal: true, isDefinition: true)
-!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_11, file: !3, producer: "clang version 22.0.0git (C:/llvm-project/clang e5cfb97d26f63942eea3c9353680fa4e669b02e7)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
-!3 = !DIFile(filename: "C:\\llvm-project\\clang\\test\\CodeGenHLSL\\debug\\<stdin>", directory: "")
-!4 = !{!0}
-!5 = !DIFile(filename: "C:\\llvm-project\\clang\\test\\CodeGenHLSL\\debug\\rwbuffer_debug_info.hlsl", directory: "")
-!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "RWBuffer<float>", scope: !7, size: 32, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !8, templateParams: !49, identifier: "_ZTSN4hlsl8RWBufferIfEE")
-!7 = !DINamespace(name: "hlsl", scope: null)
-!8 = !{!9, !12, !16, !19, !27, !28, !31, !34, !42, !46}
-!9 = !DIDerivedType(tag: DW_TAG_member, name: "__handle", scope: !6, file: !3, line: 9, baseType: !10, size: 32)
-!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32)
-!11 = !DICompositeType(tag: DW_TAG_structure_type, name: "__hlsl_resource_t", file: !3, flags: DIFlagFwdDecl)
-!12 = !DISubprogram(name: "RWBuffer", scope: !6, file: !3, type: !13, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
-!13 = !DISubroutineType(types: !14)
-!14 = !{null, !15}
-!15 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !6, size: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
-!16 = !DISubprogram(name: "RWBuffer", scope: !6, file: !3, type: !17, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
-!17 = !DISubroutineType(types: !18)
-!18 = !{null, !15, !10}
-!19 = !DISubprogram(name: "__createFromBinding", linkageName: "_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc", scope: !6, file: !3, type: !20, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0)
-!20 = !DISubroutineType(types: !21)
-!21 = !{!6, !22, !22, !23, !22, !24}
-!22 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
-!23 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!24 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !25, size: 32)
-!25 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !26)
-!26 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
-!27 = !DISubprogram(name: "__createFromImplicitBinding", linkageName: "_ZN4hlsl8RWBufferIfE27__createFromImplicitBindingEjjijPKc", scope: !6, file: !3, type: !20, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0)
-!28 = !DISubprogram(name: "RWBuffer", scope: !6, file: !3, type: !29, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
-!29 = !DISubroutineType(types: !30)
-!30 = !{null, !15, !22, !22, !23, !22, !24}
-!31 = !DISubprogram(name: "RWBuffer", scope: !6, file: !3, type: !32, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
-!32 = !DISubroutineType(types: !33)
-!33 = !{null, !15, !22, !23, !22, !22, !24}
-!34 = !DISubprogram(name: "operator[]", linkageName: "_ZNK4hlsl8RWBufferIfEixEj", scope: !6, file: !3, type: !35, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
-!35 = !DISubroutineType(types: !36)
-!36 = !{!37, !40, !22}
-!37 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !38, size: 32)
-!38 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !39)
-!39 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
-!40 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !41, size: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
-!41 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !6)
-!42 = !DISubprogram(name: "operator[]", linkageName: "_ZN4hlsl8RWBufferIfEixEj", scope: !6, file: !3, type: !43, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
-!43 = !DISubroutineType(types: !44)
-!44 = !{!45, !15, !22}
-!45 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !39, size: 32)
-!46 = !DISubprogram(name: "Load", linkageName: "_ZN4hlsl8RWBufferIfE4LoadEj", scope: !6, file: !3, type: !47, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
-!47 = !DISubroutineType(types: !48)
-!48 = !{!39, !15, !22}
-!49 = !{!50}
-!50 = !DITemplateTypeParameter(name: "element_type", type: !39)
-!51 = !{i32 7, !"Dwarf Version", i32 4}
-!52 = !{i32 2, !"Debug Info Version", i32 3}
-!53 = !{i32 1, !"wchar_size", i32 4}
-!54 = !{i32 1, i32 8}
-!55 = !{!"clang version 22.0.0git (C:/llvm-project/clang e5cfb97d26f63942eea3c9353680fa4e669b02e7)"}
-!56 = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !3, file: !3, type: !57, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2)
-!57 = !DISubroutineType(types: !58)
-!58 = !{null}
-!59 = !DILocation(line: 0, scope: !56)
-!60 = distinct !DISubprogram(name: "__createFromBinding", linkageName: "_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc", scope: !6, file: !3, line: 14, type: !20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !19, retainedNodes: !61)
-!61 = !{}
-!62 = !DILocalVariable(name: "registerNo", arg: 1, scope: !60, file: !3, type: !22)
-!63 = !DILocation(line: 0, column: 1, scope: !60)
-!64 = !DILocalVariable(name: "spaceNo", arg: 2, scope: !60, file: !3, type: !22)
-!65 = !DILocalVariable(name: "range", arg: 3, scope: !60, file: !3, type: !23)
-!66 = !DILocalVariable(name: "index", arg: 4, scope: !60, file: !3, type: !22)
-!67 = !DILocalVariable(name: "name", arg: 5, scope: !60, file: !3, type: !24)
-!68 = !DILocalVariable(name: "tmp", scope: !60, file: !3, type: !10)
-!69 = !DILocation(line: 0, scope: !60)
-!70 = !DILocation(line: 14, column: 1, scope: !60)
-!71 = distinct !DISubprogram(name: "main", linkageName: "_Z4maini", scope: !5, file: !5, line: 12, type: !72, scopeLine: 12, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !61)
-!72 = !DISubroutineType(types: !73)
-!73 = !{null, !23}
-!74 = !DILocalVariable(name: "GI", arg: 1, scope: !71, file: !5, line: 12, type: !23)
-!75 = !DILocation(line: 12, column: 15, scope: !71)
-!76 = !DILocation(line: 13, column: 7, scope: !71)
-!77 = !DILocation(line: 13, column: 3, scope: !71)
-!78 = !DILocation(line: 13, column: 11, scope: !71)
-!79 = !DILocation(line: 14, column: 1, scope: !71)
-!80 = distinct !DISubprogram(name: "operator[]", linkageName: "_ZN4hlsl8RWBufferIfEixEj", scope: !6, file: !3, line: 14, type: !43, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !42, retainedNodes: !61)
-!81 = !DILocalVariable(name: "this", arg: 1, scope: !80, type: !82, flags: DIFlagArtificial | DIFlagObjectPointer)
-!82 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !6, size: 32)
-!83 = !DILocation(line: 0, scope: !80)
-!84 = !DILocalVariable(name: "Index", arg: 2, scope: !80, file: !3, type: !22)
-!85 = !DILocation(line: 0, column: 1, scope: !80)
-!86 = !DILocation(line: 14, column: 1, scope: !80)
-!87 = distinct !DISubprogram(name: "RWBuffer", linkageName: "_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t", scope: !6, file: !3, line: 14, type: !17, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !16, retainedNodes: !61)
-!88 = !DILocalVariable(name: "this", arg: 1, scope: !87, type: !82, flags: DIFlagArtificial | DIFlagObjectPointer)
-!89 = !DILocation(line: 0, scope: !87)
-!90 = !DILocalVariable(name: "handle", arg: 2, scope: !87, file: !3, type: !10)
-!91 = !DILocation(line: 0, column: 1, scope: !87)
-!92 = !DILocation(line: 14, column: 1, scope: !87)
-!93 = !DILocation(line: 14, column: 1, scope: !94)
-!94 = !DILexicalBlockFile(scope: !87, file: !5, discriminator: 0)
-!95 = distinct !DISubprogram(name: "RWBuffer", linkageName: "_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t", scope: !6, file: !3, line: 14, type: !17, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !16, retainedNodes: !61)
-!96 = !DILocalVariable(name: "this", arg: 1, scope: !95, type: !82, flags: DIFlagArtificial | DIFlagObjectPointer)
-!97 = !DILocation(line: 0, scope: !95)
-!98 = !DILocalVariable(name: "handle", arg: 2, scope: !95, file: !3, type: !10)
-!99 = !DILocation(line: 0, column: 1, scope: !95)
-!100 = !DILocation(line: 0, scope: !101)
-!101 = distinct !DILexicalBlock(scope: !95, file: !5, line: 14, column: 1)
-!102 = !DILocation(line: 14, column: 1, scope: !103)
-!103 = !DILexicalBlockFile(scope: !95, file: !5, discriminator: 0)
-!104 = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_rwbuffer_debug_info.hlsl", scope: !3, file: !3, type: !105, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2)
-!105 = !DISubroutineType(types: !61)
-!106 = !DILocation(line: 0, scope: !104)
>From dfc07bd4df196ac59cb2ec1a0620fc7840534a77 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 3 Sep 2025 17:55:11 -0700
Subject: [PATCH 05/12] Remove handle constructor, update create methods body
and expected AST structure
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 102 ++++++++++--------
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 1 -
clang/lib/Sema/HLSLExternalSemaSource.cpp | 1 -
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 39 +++----
.../test/AST/HLSL/StructuredBuffers-AST.hlsl | 39 +++----
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 39 +++----
clang/test/SemaHLSL/Language/InitLists.hlsl | 1 -
7 files changed, 107 insertions(+), 115 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 4eac9043dab86..d635664b449c2 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -168,10 +168,13 @@ struct BuiltinTypeMethodBuilder {
template <typename... Ts>
BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
QualType ReturnType, Ts... ArgSpecs);
- template <typename T> BuiltinTypeMethodBuilder &callHandleCtor(T HandleExpr);
template <typename TLHS, typename TRHS>
BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
+ template <typename T> BuiltinTypeMethodBuilder &getResourceHandle(T ResourceRecord);
+ template <typename TResource, typename TValue>
+ BuiltinTypeMethodBuilder &setHandleFieldOnResource(TResource ResourceRecord, TValue HandleValue);
+ template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
BuiltinTypeDeclBuilder &finalize(CXXMethodDecl **OutMethod = nullptr);
Expr *getResourceHandleExpr();
@@ -503,25 +506,6 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
return *this;
}
-template <typename T>
-BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::callHandleCtor(T Handle) {
- ensureCompleteDecl();
-
- Expr *HandleExpr = convertPlaceholder(Handle);
-
- ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
- QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(DeclBuilder.Record));
- CXXConstructorDecl *Ctor = DeclBuilder.HandleCtor;
- assert(Ctor && "Handle constructor not created");
-
- CXXConstructExpr *CtorExpr = CXXConstructExpr::Create(
- AST, RecordType, SourceLocation(), Ctor, false, {HandleExpr}, false,
- false, false, false, CXXConstructionKind::Complete, SourceRange());
-
- StmtsList.push_back(CtorExpr);
- return *this;
-}
-
template <typename TLHS, typename TRHS>
BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::assign(TLHS LHS, TRHS RHS) {
Expr *LHSExpr = convertPlaceholder(LHS);
@@ -546,6 +530,51 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
return *this;
}
+template <typename T>
+BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::getResourceHandle(T ResourceRecord) {
+ ensureCompleteDecl();
+
+ Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
+ MemberExpr *HandleExpr = MemberExpr::CreateImplicit(
+ AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
+ OK_Ordinary);
+ StmtsList.push_back(HandleExpr);
+ return *this;
+}
+
+template <typename TResource, typename TValue>
+BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::setHandleFieldOnResource(TResource ResourceRecord, TValue HandleValue) {
+ ensureCompleteDecl();
+
+ Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
+ Expr *HandleValueExpr = convertPlaceholder(HandleValue);
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
+ MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
+ AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
+ OK_Ordinary);
+ Stmt *AssignStmt = BinaryOperator::Create(
+ DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr, BO_Assign,
+ HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
+ ExprObjectKind::OK_Ordinary, SourceLocation(), FPOptionsOverride());
+ StmtsList.push_back(AssignStmt);
+ return *this;
+}
+
+template <typename T>
+BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue(T ReturnValue) {
+ ensureCompleteDecl();
+
+ Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ StmtsList.push_back(ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
+ return *this;
+}
+
BuiltinTypeDeclBuilder &
BuiltinTypeMethodBuilder::finalize(CXXMethodDecl **OutMethod) {
assert(!DeclBuilder.Record->isCompleteDefinition() &&
@@ -699,23 +728,6 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor() {
.finalize();
}
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleConstructor() {
- if (Record->isCompleteDefinition())
- return *this;
-
- using PH = BuiltinTypeMethodBuilder::PlaceHolder;
- ASTContext &AST = SemaRef.getASTContext();
- QualType HandleType = getResourceHandleField()->getType();
- CXXMethodDecl *OutMethod = nullptr;
-
- BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true, AS_public)
- .addParam("handle", HandleType)
- .assign(PH::Handle, PH::_0)
- .finalize(&OutMethod);
- HandleCtor = cast<CXXConstructorDecl>(OutMethod);
- return *this;
-}
-
BuiltinTypeDeclBuilder &
BuiltinTypeDeclBuilder::addHandleConstructorFromBinding() {
if (Record->isCompleteDefinition())
@@ -775,10 +787,12 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
.addParam("range", AST.IntTy)
.addParam("index", AST.UnsignedIntTy)
.addParam("name", AST.getPointerType(AST.CharTy.withConst()))
- .createLocalVar("tmp", HandleType)
+ .createLocalVar("tmp", RecordType)
+ .getResourceHandle(PH::LocalVar_0)
.callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
- PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
- .callHandleCtor(PH::LastStmt)
+ PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
+ .setHandleFieldOnResource(PH::LocalVar_0, PH::LastStmt)
+ .returnValue(PH::LocalVar_0)
.finalize();
}
@@ -799,11 +813,13 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
.addParam("range", AST.IntTy)
.addParam("index", AST.UnsignedIntTy)
.addParam("name", AST.getPointerType(AST.CharTy.withConst()))
- .createLocalVar("tmp", HandleType)
+ .createLocalVar("tmp", RecordType)
+ .getResourceHandle(PH::LocalVar_0)
.callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
- HandleType, PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3,
+ HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
PH::_4)
- .callHandleCtor(PH::LastStmt)
+ .setHandleFieldOnResource(PH::LocalVar_0, PH::LastStmt)
+ .returnValue(PH::LocalVar_0)
.finalize();
}
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index be67e150775e2..f38bbd63b2ac1 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -80,7 +80,6 @@ class BuiltinTypeDeclBuilder {
// Builtin types constructors
BuiltinTypeDeclBuilder &addDefaultConstructor();
- BuiltinTypeDeclBuilder &addHandleConstructor();
BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 17843c4e6c751..cfc222af45f8c 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -132,7 +132,6 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
return BuiltinTypeDeclBuilder(S, Decl)
.addHandleMember(RC, IsROV, RawBuffer)
.addDefaultConstructor()
- .addHandleConstructor()
.addCreateFromBinding()
.addCreateFromImplicitBinding()
.addHandleConstructorFromBinding()
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 8336bf00ed4cb..1fef4901d7404 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -56,21 +56,6 @@ RESOURCE Buffer;
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
-// Constructor from handle
-
-// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (__hlsl_resource_t
-// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
-// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
-// CHECK-SAME{LITERAL}: [[hlsl::contained_type(char8_t)]]
-// CHECK-SAME: )' inline
-// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
-// CHECK-NEXT: CompoundStmt {{.*}}
-// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
-// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
-// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 'handle' '__hlsl_resource_t {{.*}}
-// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-
// Static __createFromBinding method
// CHECK: CXXMethodDecl {{.*}} __createFromBinding 'hlsl::[[RESOURCE]] (unsigned int, unsigned int, int, unsigned int, const char *)' static
@@ -81,18 +66,22 @@ RESOURCE Buffer;
// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
// Static __createFromImplicitBinding method
@@ -105,18 +94,22 @@ RESOURCE Buffer;
// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
// CHECK-NEXT: CompoundStmt {{.*}}
// CHECK-NEXT: DeclStmt {{.*}}
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
// Constructor from binding
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index ad481ca68b248..798af6232b124 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -103,21 +103,6 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
-// Constructor from handle
-// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (__hlsl_resource_t
-// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
-// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
-// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
-// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-SAME: )' inline
-// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
-// CHECK-NEXT: CompoundStmt {{.*}}
-// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
-// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
-// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 'handle' '__hlsl_resource_t {{.*}}
-// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-
// Static __createFromBinding method
// CHECK: CXXMethodDecl {{.*}} __createFromBinding 'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned int, const char *)' static
@@ -128,18 +113,22 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]<element_type>'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
// Static __createFromImplicitBinding method
@@ -152,18 +141,22 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
// CHECK-NEXT: CompoundStmt {{.*}}
// CHECK-NEXT: DeclStmt {{.*}}
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]<element_type>'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
// Constructor from binding
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 3484d088eb17a..cc3d9cc399499 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -78,21 +78,6 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
-// Constructor from handle
-
-// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (__hlsl_resource_t
-// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
-// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
-// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-SAME: )' inline
-// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
-// CHECK-NEXT: CompoundStmt {{.*}}
-// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
-// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
-// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 'handle' '__hlsl_resource_t {{.*}}
-// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-
// Static __createFromBinding method
// CHECK: CXXMethodDecl {{.*}} __createFromBinding 'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned int, const char *)' static
@@ -103,18 +88,22 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]<element_type>'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
// Static __createFromImplicitBinding method
@@ -127,18 +116,22 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
// CHECK-NEXT: CompoundStmt {{.*}}
// CHECK-NEXT: DeclStmt {{.*}}
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]<element_type>'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
// Constructor from binding
diff --git a/clang/test/SemaHLSL/Language/InitLists.hlsl b/clang/test/SemaHLSL/Language/InitLists.hlsl
index 524f6ac220092..3607dfd8aedbc 100644
--- a/clang/test/SemaHLSL/Language/InitLists.hlsl
+++ b/clang/test/SemaHLSL/Language/InitLists.hlsl
@@ -124,4 +124,3 @@ void Err2(RWBuffer<float4> B) {
// These notes refer to the RWBuffer constructors that do not have source locations
// expected-note@*{{candidate constructor (the implicit copy constructor) not viable}}
// expected-note@*{{candidate constructor (the implicit move constructor) not viable}}
-// expected-note@*{{candidate constructor not viable}}
>From e7641e13fb3f85e8978a7f4c25847e0fd817ace9 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 3 Sep 2025 18:56:32 -0700
Subject: [PATCH 06/12] cleanup
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 8 +++-----
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 4 +---
clang/lib/Sema/HLSLExternalSemaSource.cpp | 2 +-
3 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index d635664b449c2..3ccda084f3813 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -175,7 +175,7 @@ struct BuiltinTypeMethodBuilder {
template <typename TResource, typename TValue>
BuiltinTypeMethodBuilder &setHandleFieldOnResource(TResource ResourceRecord, TValue HandleValue);
template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
- BuiltinTypeDeclBuilder &finalize(CXXMethodDecl **OutMethod = nullptr);
+ BuiltinTypeDeclBuilder &finalize();
Expr *getResourceHandleExpr();
private:
@@ -576,7 +576,7 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue(T ReturnValue) {
}
BuiltinTypeDeclBuilder &
-BuiltinTypeMethodBuilder::finalize(CXXMethodDecl **OutMethod) {
+BuiltinTypeMethodBuilder::finalize() {
assert(!DeclBuilder.Record->isCompleteDefinition() &&
"record is already complete");
@@ -608,8 +608,6 @@ BuiltinTypeMethodBuilder::finalize(CXXMethodDecl **OutMethod) {
AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
DeclBuilder.Record->addDecl(Method);
}
- if (OutMethod)
- *OutMethod = Method;
return DeclBuilder;
}
@@ -714,7 +712,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
// Adds default constructor to the resource class:
// Resource::Resource()
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor() {
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
if (Record->isCompleteDefinition())
return *this;
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index f38bbd63b2ac1..ba860a9080cea 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -25,7 +25,6 @@ namespace clang {
class ClassTemplateDecl;
class NamespaceDecl;
class CXXRecordDecl;
-class CXXConstructorDecl;
class FieldDecl;
namespace hlsl {
@@ -53,7 +52,6 @@ class BuiltinTypeDeclBuilder {
ClassTemplateDecl *PrevTemplate = nullptr;
NamespaceDecl *HLSLNamespace = nullptr;
llvm::StringMap<FieldDecl *> Fields;
- CXXConstructorDecl *HandleCtor = nullptr;
public:
friend struct TemplateParameterListBuilder;
@@ -79,7 +77,7 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &addArraySubscriptOperators();
// Builtin types constructors
- BuiltinTypeDeclBuilder &addDefaultConstructor();
+ BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index cfc222af45f8c..a5d51ca7d35be 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -131,7 +131,7 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
bool RawBuffer) {
return BuiltinTypeDeclBuilder(S, Decl)
.addHandleMember(RC, IsROV, RawBuffer)
- .addDefaultConstructor()
+ .addDefaultHandleConstructor()
.addCreateFromBinding()
.addCreateFromImplicitBinding()
.addHandleConstructorFromBinding()
>From 60281945d38c5bb7e7ea6ff4fcbaf7787aaf7d16 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 3 Sep 2025 18:58:27 -0700
Subject: [PATCH 07/12] clang-format
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 23 +++++++++++--------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 3ccda084f3813..a4d75155d8511 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -171,9 +171,11 @@ struct BuiltinTypeMethodBuilder {
template <typename TLHS, typename TRHS>
BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
- template <typename T> BuiltinTypeMethodBuilder &getResourceHandle(T ResourceRecord);
+ template <typename T>
+ BuiltinTypeMethodBuilder &getResourceHandle(T ResourceRecord);
template <typename TResource, typename TValue>
- BuiltinTypeMethodBuilder &setHandleFieldOnResource(TResource ResourceRecord, TValue HandleValue);
+ BuiltinTypeMethodBuilder &setHandleFieldOnResource(TResource ResourceRecord,
+ TValue HandleValue);
template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
BuiltinTypeDeclBuilder &finalize();
Expr *getResourceHandleExpr();
@@ -531,7 +533,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
}
template <typename T>
-BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::getResourceHandle(T ResourceRecord) {
+BuiltinTypeMethodBuilder &
+BuiltinTypeMethodBuilder::getResourceHandle(T ResourceRecord) {
ensureCompleteDecl();
Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
@@ -546,7 +549,9 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::getResourceHandle(T Resource
}
template <typename TResource, typename TValue>
-BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::setHandleFieldOnResource(TResource ResourceRecord, TValue HandleValue) {
+BuiltinTypeMethodBuilder &
+BuiltinTypeMethodBuilder::setHandleFieldOnResource(TResource ResourceRecord,
+ TValue HandleValue) {
ensureCompleteDecl();
Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
@@ -558,8 +563,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::setHandleFieldOnResource(TRe
AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
OK_Ordinary);
Stmt *AssignStmt = BinaryOperator::Create(
- DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr, BO_Assign,
- HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
+ DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr,
+ BO_Assign, HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
ExprObjectKind::OK_Ordinary, SourceLocation(), FPOptionsOverride());
StmtsList.push_back(AssignStmt);
return *this;
@@ -571,12 +576,12 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue(T ReturnValue) {
Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
- StmtsList.push_back(ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
+ StmtsList.push_back(
+ ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
return *this;
}
-BuiltinTypeDeclBuilder &
-BuiltinTypeMethodBuilder::finalize() {
+BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
assert(!DeclBuilder.Record->isCompleteDefinition() &&
"record is already complete");
>From e7d6ee69558321a636358a10d9e0fb792ccecdc0 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 3 Sep 2025 20:46:43 -0700
Subject: [PATCH 08/12] Update tests after create methods body change
---
.../CodeGenHLSL/GlobalConstructorLib.hlsl | 5 ++-
.../ByteAddressBuffers-constructors.hlsl | 28 +++++-------
.../resources/RWBuffer-constructor.hlsl | 28 +++++-------
.../StructuredBuffers-constructors.hlsl | 44 ++++++++-----------
4 files changed, 41 insertions(+), 64 deletions(-)
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
index c3d4fbb12a6f4..fa703b0a0a1d2 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
@@ -33,9 +33,10 @@ void SecondEntry() {}
// Verify the constructors are alwaysinline
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
-// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(ptr {{.*}} %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) {{.*}} [[CtorAttr:\#[0-9]+]]
+// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]]
+
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
-// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr {{.*}} %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) {{.*}} [[CtorAttr]]
+// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]]
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[InitAttr:\#[0-9]+]]
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
index 35e1c14a0931f..193ce1dd1251b 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
@@ -36,12 +36,14 @@ export void foo() {
// Buf1 initialization part 2 - body of ByteAddressBuffer::__createFromBinding
// CHECK: define {{.*}} void @_ZN4hlsl17ByteAddressBuffer19__createFromBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::ByteAddressBuffer") align 4 %[[Tmp1:.*]], i32 noundef %registerNo,
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::ByteAddressBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::ByteAddressBuffer", align 4
// CHECK: %[[Handle1:.*]] = call target("dx.RawBuffer", i8, 0, 0)
// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
-// CHECK: call void @_ZN4hlsl17ByteAddressBufferC1EU13_Res_t_Raw_CTDuu17__hlsl_resource_t(
-// CHECK-SAME: ptr {{.*}} %[[Tmp1]], target("dx.RawBuffer", i8, 0, 0) %[[Handle1]])
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %[[Tmp1]], i32 0, i32 0
+// CHECK-DXIL: store target("dx.RawBuffer", i8, 0, 0) %[[Handle1]], ptr %__handle, align 4
+// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue1]], ptr align 4 %[[Tmp1]], i32 4, i1 false)
// Buf2 initialization part 1 - global init function that calls RWByteAddressBuffer::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
@@ -51,12 +53,14 @@ export void foo() {
// Buf2 initialization part 2 - body of RWByteAddressBuffer::__createFromImplicitBinding
// CHECK: define hidden void @_ZN4hlsl19RWByteAddressBuffer27__createFromImplicitBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWByteAddressBuffer") align 4 %[[Tmp2:.*]], i32 noundef %orderId,
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWByteAddressBuffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWByteAddressBuffer", align 4
// CHECK: %[[Handle2:.*]] = call target("dx.RawBuffer", i8, 1, 0)
// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i8_1_0t(
-// CHECK: call void @_ZN4hlsl19RWByteAddressBufferC1EU13_Res_u_Raw_CTDuu17__hlsl_resource_t(
-// CHECK-SAME: ptr {{.*}} %[[Tmp2]], target("dx.RawBuffer", i8, 1, 0) %[[Handle2]])
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %[[Tmp2]], i32 0, i32 0
+// CHECK-DXIL: store target("dx.RawBuffer", i8, 1, 0) %[[Handle2]], ptr %__handle, align 4
+// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue2]], ptr align 4 %[[Tmp2]], i32 4, i1 false)
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// RasterizerOrderedByteAddressBuffer C1 default constructor
@@ -71,18 +75,6 @@ export void foo() {
// CHECK: call void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}})
// CHECK-NEXT: ret void
-// Buf1 initialization part 3 - ByteAddressBuffer constructor constructor with handle
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl17ByteAddressBufferC2EU13_Res_t_Raw_CTDuu17__hlsl_resource_t(ptr {{.*}} %this,
-// CHECK-SAME: target("dx.RawBuffer", i8, 0, 0) %handle)
-// CHECK: %[[HandlePtr1:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %{{.*}}, ptr %[[HandlePtr1]], align 4
-
-// Buf2 initialization part 3 - body of RWByteAddressBuffer constructor with handle
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl19RWByteAddressBufferC1EU13_Res_u_Raw_CTDuu17__hlsl_resource_t(ptr {{.*}} %this,
-// CHECK-SAME: target("dx.RawBuffer", i8, 1, 0) %handle)
-// CHECK: %[[HandlePtr2:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 0) %{{.*}}, ptr %[[HandlePtr2]], align 4
-
// Buf3 initialization part 3 - body of RasterizerOrderedByteAddressBuffer default C2 constructor that
// initializes handle to poison
// CHECK: define linkonce_odr hidden void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
index c5c40449c6c8e..75db79d5a196d 100644
--- a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
@@ -36,12 +36,14 @@ export void foo() {
// Buf1 initialization part 2 - body of RWBuffer<float>::__createFromBinding
// CHECK: define {{.*}} void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp1:.*]], i32 noundef %registerNo,
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer", align 4
// CHECK: %[[Handle1:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0)
// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(
-// CHECK: call void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(
-// CHECK-SAME: ptr {{.*}} %[[Tmp1]], target("dx.TypedBuffer", float, 1, 0, 0) %[[Handle1]])
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %[[Tmp1]], i32 0, i32 0
+// CHECK-DXIL: store target("dx.TypedBuffer", float, 1, 0, 0) %[[Handle1]], ptr %__handle, align 4
+// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue1]], ptr align 4 %[[Tmp1]], i32 4, i1 false)
// Buf2 initialization part 1 - global init function that RWBuffer<float>::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
@@ -51,12 +53,14 @@ export void foo() {
// Buf2 initialization part 2 - body of RWBuffer<float>::__createFromImplicitBinding call
// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp2:.*]], i32 noundef %orderId,
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
+// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer.0", align 4
// CHECK: %[[Handle2:.*]] = call target("dx.TypedBuffer", double, 1, 0, 0)
// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_1_0_0t(
-// CHECK: call void @_ZN4hlsl8RWBufferIdEC1EU9_Res_u_CTdu17__hlsl_resource_t(
-// CHECK-SAME: ptr {{.*}} %[[Tmp2]], target("dx.TypedBuffer", double, 1, 0, 0) %[[Handle2]])
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %[[Tmp2]], i32 0, i32 0
+// CHECK-DXIL: store target("dx.TypedBuffer", double, 1, 0, 0) %[[Handle2]], ptr %__handle, align 4
+// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue2]], ptr align 4 %[[Tmp2]], i32 4, i1 false)
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by RWBuffer<int> C1 default constructor
// CHECK: define void @_Z3foov()
@@ -68,18 +72,6 @@ export void foo() {
// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC1Ev(ptr {{.*}} %this)
// CHECK: call void @_ZN4hlsl8RWBufferIiEC2Ev(ptr {{.*}} %{{.*}})
-// Buf1 initialization part 3 - body of RWBuffer<float> constructor with handle
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr {{.*}} %this,
-// CHECK-SAME: target("dx.TypedBuffer", float, 1, 0, 0) %handle)
-// CHECK: %[[HandlePtr1:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %{{.*}}, ptr %[[HandlePtr1]], align 4
-
-// Buf2 initialization part 3 - body of RWBuffer<double> constructor with handle
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdEC1EU9_Res_u_CTdu17__hlsl_resource_t(ptr {{.*}} %this,
-// CHECK-SAME: target("dx.TypedBuffer", double, 1, 0, 0) %handle)
-// CHECK: %[[HandlePtr2:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", double, 1, 0, 0) %{{.*}}, ptr %[[HandlePtr2]], align 4
-
// Buf3 initialization part 3 - body of RWBuffer<int> default C2 constructor that initializes handle to poison
// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC2Ev(ptr {{.*}} %this)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.1", ptr %{{.*}}, i32 0, i32 0
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
index 834a9639484a5..1939f28a1f2ff 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
@@ -18,9 +18,9 @@ export void foo() {
AppendStructuredBuffer<float> Buf3;
}
-// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
-// CHECK: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
+// CHECK-DXIL: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) }
+// CHECK-DXIL: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
+// CHECK-DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
// CHECK: @_ZL4Buf1 = internal global %"class.hlsl::StructuredBuffer" poison, align 4
// CHECK: @[[Buf1Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf1\00", align 1
@@ -37,12 +37,14 @@ export void foo() {
// Buf1 initialization part 2 - body of StructuredBuffer<float>::::__createFromBinding
// CHECK: define {{.*}} void @_ZN4hlsl16StructuredBufferIfE19__createFromBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::StructuredBuffer") align 4 %[[Tmp1:.*]], i32 noundef %registerNo,
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::StructuredBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
-// CHECK: %[[Handle1:.*]] = call target("dx.RawBuffer", float, 0, 0)
-// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(
-// CHECK: call void @_ZN4hlsl16StructuredBufferIfEC1EU13_Res_t_Raw_CTfu17__hlsl_resource_t(
-// CHECK-SAME: ptr {{.*}} %[[Tmp1]], target("dx.RawBuffer", float, 0, 0) %[[Handle1]])
+// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::StructuredBuffer", align 4
+// CHECK-DXIL: %[[Handle1:.*]] = call target("dx.RawBuffer", float, 0, 0)
+// CHECK-DXIL-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %[[Tmp1]], i32 0, i32 0
+// CHECK-DXIL: store target("dx.RawBuffer", float, 0, 0) %[[Handle1]], ptr %__handle, align 4
+// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue1]], ptr align 4 %[[Tmp1]], i32 4, i1 false)
// Buf2 initialization part 1 - global init function that calls RWStructuredBuffer<float>::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
@@ -52,12 +54,14 @@ export void foo() {
// Buf2 initialization part 2 - body of RWStructuredBuffer<float>::__createFromImplicitBinding
// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfE27__createFromImplicitBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWStructuredBuffer") align 4 %[[Tmp2:.*]], i32 noundef %orderId,
+// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWStructuredBuffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
-// CHECK: %[[Handle2:.*]] = call target("dx.RawBuffer", float, 1, 0)
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f32_1_0t(
-// CHECK: call void @_ZN4hlsl18RWStructuredBufferIfEC1EU13_Res_u_Raw_CTfu17__hlsl_resource_t(
-// CHECK-SAME: ptr {{.*}} %[[Tmp2]], target("dx.RawBuffer", float, 1, 0) %[[Handle2]])
+// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWStructuredBuffer", align 4
+// CHECK-DXIL: %[[Handle2:.*]] = call target("dx.RawBuffer", float, 1, 0)
+// CHECK-DXIL-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f32_1_0t(
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %[[Tmp2]], i32 0, i32 0
+// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) %[[Handle2]], ptr %__handle, align 4
+// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue2]], ptr align 4 %[[Tmp2]], i32 4, i1 false)
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// AppendStructuredBuffer<float> C1 default constructor
@@ -71,23 +75,11 @@ export void foo() {
// CHECK: define linkonce_odr hidden void @_ZN4hlsl22AppendStructuredBufferIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
// CHECK: call void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}})
-// Buf1 initialization part 3 - body of StructuredBuffer<float> constructor with handle
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl16StructuredBufferIfEC1EU13_Res_t_Raw_CTfu17__hlsl_resource_t(ptr {{.*}} %this,
-// CHECK-SAME: target("dx.RawBuffer", float, 0, 0) %handle)
-// CHECK: %[[HandlePtr1:.*]] = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %{{.*}}, ptr %[[HandlePtr1]], align 4
-
-// Buf2 initialization part 3 - body of RWStructuredBuffer<float> constructor with handle
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfEC2EU13_Res_u_Raw_CTfu17__hlsl_resource_t(ptr {{.*}} %this,
-// CHECK-SAME: target("dx.RawBuffer", float, 1, 0) %handle)
-// CHECK: %[[HandlePtr2:.*]] = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %{{.*}}, ptr %[[HandlePtr2]], align 4
-
// Buf3 initialization part 3 - body of AppendStructuredBuffer<float> default C2 constructor that
// initializes handle to poison
// CHECK: define linkonce_odr hidden void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::AppendStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
-// CHECK: store target("dx.RawBuffer", float, 1, 0) poison, ptr %__handle, align 4
+// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) poison, ptr %__handle, align 4
// Module initialization
// CHECK: define internal void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl()
>From 7782eeab76ef6b205ea70c4f7e8072dc5c60cc02 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 4 Sep 2025 15:45:07 -0700
Subject: [PATCH 09/12] Update tests to use llvm-cxxfilt to have unmangled
names in the baselines
---
clang/lib/Sema/SemaHLSL.cpp | 2 +-
.../CodeGenHLSL/GlobalConstructorLib.hlsl | 12 +++----
.../ByteAddressBuffers-constructors.hlsl | 36 ++++++++++---------
.../resources/RWBuffer-constructor.hlsl | 36 ++++++++++---------
.../StructuredBuffers-constructors.hlsl | 34 +++++++++---------
.../resources/resource-bindings.hlsl | 3 +-
clang/test/CodeGenHLSL/static-local-ctor.hlsl | 11 +++---
7 files changed, 71 insertions(+), 63 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 63ca46583a59b..775098d06b18c 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3767,7 +3767,7 @@ bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
SpaceNo = RBA->getSpaceNumber();
}
- // Find correct initialization method and create its argumentss.
+ // Find correct initialization method and create its arguments.
QualType ResourceTy = VD->getType();
CXXRecordDecl *ResourceDecl = ResourceTy->getAsCXXRecordDecl();
CXXMethodDecl *CreateMethod = nullptr;
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
index fa703b0a0a1d2..3cb7827e26884 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,INLINE
// Make sure global variable for ctors exist for lib profile.
// CHECK:@llvm.global_ctors
@@ -13,7 +13,7 @@ void FirstEntry() {}
// CHECK: define void @FirstEntry()
// CHECK-NEXT: entry:
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
-// NOINLINE-NEXT: call void @_Z10FirstEntryv()
+// NOINLINE-NEXT: call void @FirstEntry()
// Verify inlining leaves only calls to "llvm." intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void
@@ -25,7 +25,7 @@ void SecondEntry() {}
// CHECK: define void @SecondEntry()
// CHECK-NEXT: entry:
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
-// NOINLINE-NEXT: call void @_Z11SecondEntryv()
+// NOINLINE-NEXT: call void @SecondEntry()
// Verify inlining leaves only calls to "llvm." intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void
@@ -33,10 +33,10 @@ void SecondEntry() {}
// Verify the constructors are alwaysinline
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
-// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]]
+// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer<float>::RWBuffer()(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]]
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
-// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]]
+// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer<float>::RWBuffer()(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]]
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[InitAttr:\#[0-9]+]]
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
index 193ce1dd1251b..71ff3bf16afcc 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
@@ -1,6 +1,8 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | \
+// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
// FIXME: SPIR-V codegen of llvm.spv.resource.handlefrombinding and resource types is not yet implemented
-// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | \
+// llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
// NOTE: Itanium ABI for C++ requires Clang to generate 2 constructors types to support polymorphism:
// - C1 - Complete object constructor - constructs the complete object, including virtual base classes.
@@ -23,20 +25,20 @@ export void foo() {
// CHECK: %"class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) }
// CHECK: %"class.hlsl::RasterizerOrderedByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 1) }
-// CHECK: @_ZL4Buf1 = internal global %"class.hlsl::ByteAddressBuffer" poison, align 4
+// CHECK: @Buf1 = internal global %"class.hlsl::ByteAddressBuffer" poison, align 4
// CHECK: @[[Buf1Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf1\00", align 1
-// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWByteAddressBuffer" poison, align 4
+// CHECK: @Buf2 = internal global %"class.hlsl::RWByteAddressBuffer" poison, align 4
// CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1
// Buf1 initialization part 1 - global init function that calls ByteAddressBuffer::__createFromBinding
// CHECK: define internal void @__cxx_global_var_init()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl17ByteAddressBuffer19__createFromBindingEjjijPKc(ptr {{.*}} @_ZL4Buf1,
-// CHECK-SAME: i32 noundef 1, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
+// CHECK-NEXT: call void @hlsl::ByteAddressBuffer::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} @Buf1, i32 noundef 1, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
// Buf1 initialization part 2 - body of ByteAddressBuffer::__createFromBinding
-// CHECK: define {{.*}} void @_ZN4hlsl17ByteAddressBuffer19__createFromBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::ByteAddressBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo,
+// CHECK: define {{.*}} void @hlsl::ByteAddressBuffer::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::ByteAddressBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::ByteAddressBuffer", align 4
// CHECK: %[[Handle1:.*]] = call target("dx.RawBuffer", i8, 0, 0)
@@ -48,12 +50,12 @@ export void foo() {
// Buf2 initialization part 1 - global init function that calls RWByteAddressBuffer::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl19RWByteAddressBuffer27__createFromImplicitBindingEjjijPKc(ptr {{.*}} @_ZL4Buf2,
-// CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
+// CHECK-NEXT: call void @hlsl::RWByteAddressBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} @Buf2, i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
// Buf2 initialization part 2 - body of RWByteAddressBuffer::__createFromImplicitBinding
-// CHECK: define hidden void @_ZN4hlsl19RWByteAddressBuffer27__createFromImplicitBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWByteAddressBuffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
+// CHECK: define hidden void @hlsl::RWByteAddressBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWByteAddressBuffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWByteAddressBuffer", align 4
// CHECK: %[[Handle2:.*]] = call target("dx.RawBuffer", i8, 1, 0)
@@ -64,20 +66,20 @@ export void foo() {
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// RasterizerOrderedByteAddressBuffer C1 default constructor
-// CHECK: define void @_Z3foov()
+// CHECK: define void @foo()
// CHECK-NEXT: entry:
// CHECK-NEXT: %Buf3 = alloca %"class.hlsl::RasterizerOrderedByteAddressBuffer", align 4
-// CHECK-NEXT: call void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %Buf3)
+// CHECK-NEXT: call void @hlsl::RasterizerOrderedByteAddressBuffer::RasterizerOrderedByteAddressBuffer()(ptr {{.*}} %Buf3)
// Buf3 initialization part 2 - body of RasterizerOrderedByteAddressBuffer default C1 constructor that
// calls the default C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
-// CHECK: call void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}})
+// CHECK: define linkonce_odr hidden void @hlsl::RasterizerOrderedByteAddressBuffer::RasterizerOrderedByteAddressBuffer()(ptr {{.*}} %this)
+// CHECK: call void @hlsl::RasterizerOrderedByteAddressBuffer::RasterizerOrderedByteAddressBuffer()(ptr {{.*}} %this1)
// CHECK-NEXT: ret void
// Buf3 initialization part 3 - body of RasterizerOrderedByteAddressBuffer default C2 constructor that
// initializes handle to poison
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
+// CHECK: define linkonce_odr hidden void @hlsl::RasterizerOrderedByteAddressBuffer::RasterizerOrderedByteAddressBuffer()(ptr {{.*}} %this)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK: store target("dx.RawBuffer", i8, 1, 1) poison, ptr %__handle, align 4
diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
index 75db79d5a196d..47ba8bec2bfce 100644
--- a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
@@ -1,6 +1,8 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | \
+// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
// FIXME: SPIR-V codegen of llvm.spv.resource.handlefrombinding and resource types is not yet implemented
-// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | \
+// llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
// NOTE: Itanium ABI for C++ requires Clang to generate 2 constructors types to support polymorphism:
// - C1 - Complete object constructor - constructs the complete object, including virtual base classes.
@@ -23,20 +25,20 @@ export void foo() {
// CHECK: %"class.hlsl::RWBuffer.0" = type { target("dx.TypedBuffer", double, 1, 0, 0) }
// CHECK: %"class.hlsl::RWBuffer.1" = type { target("dx.TypedBuffer", i32, 1, 0, 1) }
-// CHECK: @_ZL4Buf1 = internal global %"class.hlsl::RWBuffer" poison, align 4
+// CHECK: @Buf1 = internal global %"class.hlsl::RWBuffer" poison, align 4
// CHECK: @[[Buf1Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf1\00", align 1
-// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWBuffer.0" poison, align 4
+// CHECK: @Buf2 = internal global %"class.hlsl::RWBuffer.0" poison, align 4
// CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1
// Buf1 initialization part 1 - global init function that calls RWBuffer<float>::__createFromBinding
// CHECK: define internal void @__cxx_global_var_init()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 @_ZL4Buf1,
-// CHECK-SAME: i32 noundef 5, i32 noundef 3, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
+// CHECK-NEXT: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 @Buf1, i32 noundef 5, i32 noundef 3, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
// Buf1 initialization part 2 - body of RWBuffer<float>::__createFromBinding
-// CHECK: define {{.*}} void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo,
+// CHECK: define {{.*}} void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer", align 4
// CHECK: %[[Handle1:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0)
@@ -48,12 +50,12 @@ export void foo() {
// Buf2 initialization part 1 - global init function that RWBuffer<float>::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} @_ZL4Buf2,
-// CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
+// CHECK-NEXT: call void @hlsl::RWBuffer<double>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} @Buf2, i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
// Buf2 initialization part 2 - body of RWBuffer<float>::__createFromImplicitBinding call
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
+// CHECK: define linkonce_odr hidden void @hlsl::RWBuffer<double>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer.0", align 4
// CHECK: %[[Handle2:.*]] = call target("dx.TypedBuffer", double, 1, 0, 0)
@@ -63,17 +65,17 @@ export void foo() {
// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue2]], ptr align 4 %[[Tmp2]], i32 4, i1 false)
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by RWBuffer<int> C1 default constructor
-// CHECK: define void @_Z3foov()
+// CHECK: define void @foo()
// CHECK-NEXT: entry:
// CHECK-NEXT: %Buf3 = alloca %"class.hlsl::RWBuffer.1", align 4
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1Ev(ptr {{.*}} %Buf3)
+// CHECK-NEXT: call void @hlsl::RWBuffer<int>::RWBuffer()(ptr {{.*}} %Buf3)
// Buf3 initialization part 2 - body of RWBuffer<int> default C1 constructor that calls the default C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC1Ev(ptr {{.*}} %this)
-// CHECK: call void @_ZN4hlsl8RWBufferIiEC2Ev(ptr {{.*}} %{{.*}})
+// CHECK: define linkonce_odr hidden void @hlsl::RWBuffer<int>::RWBuffer()(ptr {{.*}} %this)
+// CHECK: call void @hlsl::RWBuffer<int>::RWBuffer()(ptr {{.*}} %{{.*}})
// Buf3 initialization part 3 - body of RWBuffer<int> default C2 constructor that initializes handle to poison
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC2Ev(ptr {{.*}} %this)
+// CHECK: define linkonce_odr hidden void @hlsl::RWBuffer<int>::RWBuffer()(ptr {{.*}} %this)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.1", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: store target("dx.TypedBuffer", i32, 1, 0, 1) poison, ptr %__handle, align 4
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
index 1939f28a1f2ff..d342c8ab456e2 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
@@ -1,6 +1,8 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | \
+// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
// FIXME: SPIR-V codegen of llvm.spv.resource.handlefrombinding and resource types is not yet implemented
-// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | \
+// llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
// NOTE: Itanium ABI for C++ requires Clang to generate 2 constructors types to support polymorphism:
// - C1 - Complete object constructor - constructs the complete object, including virtual base classes.
@@ -22,21 +24,21 @@ export void foo() {
// CHECK-DXIL: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
// CHECK-DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
-// CHECK: @_ZL4Buf1 = internal global %"class.hlsl::StructuredBuffer" poison, align 4
+// CHECK: @Buf1 = internal global %"class.hlsl::StructuredBuffer" poison, align 4
// CHECK: @[[Buf1Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf1\00", align 1
-// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+// CHECK: @Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
// CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1
// Buf1 initialization part 1 - global init function that calls StructuredBuffer<float>::__createFromBinding
// with explicit binding
// CHECK: define internal void @__cxx_global_var_init()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl16StructuredBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} @_ZL4Buf1,
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
+// CHECK-NEXT: call void @hlsl::StructuredBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} @Buf1, i32 noundef 10, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]])
// Buf1 initialization part 2 - body of StructuredBuffer<float>::::__createFromBinding
-// CHECK: define {{.*}} void @_ZN4hlsl16StructuredBufferIfE19__createFromBindingEjjijPKc(
+// CHECK: define {{.*}} void @hlsl::StructuredBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::StructuredBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::StructuredBuffer", align 4
@@ -49,12 +51,12 @@ export void foo() {
// Buf2 initialization part 1 - global init function that calls RWStructuredBuffer<float>::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @_ZN4hlsl18RWStructuredBufferIfE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} @_ZL4Buf2,
-// CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
+// CHECK-NEXT: call void @hlsl::RWStructuredBuffer<float>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} @Buf2, i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]])
// Buf2 initialization part 2 - body of RWStructuredBuffer<float>::__createFromImplicitBinding
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfE27__createFromImplicitBindingEjjijPKc(
-// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::RWStructuredBuffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
+// CHECK: define linkonce_odr hidden void @hlsl::RWStructuredBuffer<float>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWStructuredBuffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name)
// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWStructuredBuffer", align 4
// CHECK-DXIL: %[[Handle2:.*]] = call target("dx.RawBuffer", float, 1, 0)
@@ -65,19 +67,19 @@ export void foo() {
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// AppendStructuredBuffer<float> C1 default constructor
-// CHECK: define void @_Z3foov()
+// CHECK: define void @foo()
// CHECK-NEXT: entry:
// CHECK-NEXT: %Buf3 = alloca %"class.hlsl::AppendStructuredBuffer", align 4
-// CHECK-NEXT: call void @_ZN4hlsl22AppendStructuredBufferIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %Buf3)
+// CHECK-NEXT: call void @hlsl::AppendStructuredBuffer<float>::AppendStructuredBuffer()(ptr {{.*}} %Buf3)
// Buf3 initialization part 2 - body of AppendStructuredBuffer<float> default C1 constructor that calls
// the default C2 constructor
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl22AppendStructuredBufferIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
-// CHECK: call void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}})
+// CHECK: define linkonce_odr hidden void @hlsl::StructuredBuffer<float>::StructuredBuffer()(ptr {{.*}} %this)
+// CHECK: call void @hlsl::StructuredBuffer<float>::StructuredBuffer()(ptr {{.*}} %this1)
// Buf3 initialization part 3 - body of AppendStructuredBuffer<float> default C2 constructor that
// initializes handle to poison
-// CHECK: define linkonce_odr hidden void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
+// CHECK: define linkonce_odr hidden void @hlsl::StructuredBuffer<float>::StructuredBuffer()(ptr {{.*}} %this)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::AppendStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) poison, ptr %__handle, align 4
diff --git a/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl b/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl
index 8884e391ec917..4ffa7cfc84e17 100644
--- a/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl
+++ b/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil--shadermodel6.6-compute -x hlsl -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple dxil--shadermodel6.6-compute -x hlsl -finclude-default-header \
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
// CHECK: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", <4 x float>, 1, 0, 0) }
// CHECK: %"class.hlsl::RWBuffer.0" = type { target("dx.TypedBuffer", float, 1, 0, 0) }
diff --git a/clang/test/CodeGenHLSL/static-local-ctor.hlsl b/clang/test/CodeGenHLSL/static-local-ctor.hlsl
index f44d70dff7811..bb575d23216b0 100644
--- a/clang/test/CodeGenHLSL/static-local-ctor.hlsl
+++ b/clang/test/CodeGenHLSL/static-local-ctor.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -disable-llvm-passes %s | \
+// RUN: llvm-cxxfilt | FileCheck %s
// Verify that no per variable _Init_thread instructions are emitted for non-trivial static locals
// These would normally be emitted by the MicrosoftCXXABI, but the DirectX backend should exlude them
@@ -13,17 +14,17 @@ void InitBuf(RWBuffer<int> buf) {
}
// CHECK-NOT: _Init_thread_epoch
-// CHECK: define internal void @_Z4mainv
+// CHECK: define internal void @main
// CHECK-NEXT: entry:
// CHECK-NEXT: [[Tmp0:%.*]] = alloca %"class.hlsl::RWBuffer"
// CHECK-NEXT: [[Tmp1:%.*]] = alloca %"class.hlsl::RWBuffer"
-// CHECK-NEXT: [[Tmp2:%.*]] = load i8, ptr @_ZGVZ4mainvE5mybuf
+// CHECK-NEXT: [[Tmp2:%.*]] = load i8, ptr @guard variable for main()::mybuf
// CHECK-NEXT: [[Tmp3:%.*]] = icmp eq i8 [[Tmp2]], 0
// CHECK-NEXT: br i1 [[Tmp3]]
// CHECK-NOT: _Init_thread_header
// CHECK: init.check:
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiE27__createFromImplicitBindingEjjijPKc(
-// CHECK-NEXT: store i8 1, ptr @_ZGVZ4mainvE5mybuf
+// CHECK-NEXT: call void @hlsl::RWBuffer<int>::__createFromImplicitBinding
+// CHECK-NEXT: store i8 1, ptr @guard variable for main()::mybuf
// CHECK-NOT: _Init_thread_footer
>From c7b35b90d1276454ad30efdc22b8a9690e8e642f Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 10 Sep 2025 21:31:58 -0700
Subject: [PATCH 10/12] update PR after merge from main that introduced
explicit copy constructor for resource classes
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 23 +++++++++++++++++++
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 4 ++++
.../CodeGenHLSL/GlobalConstructorLib.hlsl | 8 ++++++-
.../ByteAddressBuffers-constructors.hlsl | 4 ++--
.../resources/RWBuffer-constructor.hlsl | 4 ++--
.../StructuredBuffers-constructors.hlsl | 4 ++--
6 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 97c8881c9e3b4..a08a6fa11ce5b 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
@@ -48,6 +49,14 @@ static FunctionDecl *lookupBuiltinFunction(Sema &S, StringRef Name) {
"Since this is a builtin it should always resolve!");
return cast<FunctionDecl>(R.getFoundDecl());
}
+
+CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
+ assert(ResTy->isRecordType() && "not a CXXRecord type");
+ for (auto *CD : ResTy->getAsCXXRecordDecl()->ctors())
+ if (CD->isCopyConstructor())
+ return CD;
+ return nullptr;
+}
} // namespace
// Builder for template arguments of builtin types. Used internally
@@ -601,6 +610,20 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue(T ReturnValue) {
Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+
+ QualType Ty = ReturnValueExpr->getType();
+ if (Ty->isRecordType()) {
+ // For record types, create a call to copy constructor to ensure proper copy
+ // semantics.
+ auto *ICE =
+ ImplicitCastExpr::Create(AST, Ty.withConst(), CK_NoOp, ReturnValueExpr,
+ nullptr, VK_XValue, FPOptionsOverride());
+ CXXConstructorDecl *CD = lookupCopyConstructor(Ty);
+ assert(CD && "no copy constructor found");
+ ReturnValueExpr = CXXConstructExpr::Create(
+ AST, Ty, SourceLocation(), CD, false, {ICE}, false, false, false, false,
+ CXXConstructionKind::Complete, SourceRange());
+ }
StmtsList.push_back(
ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
return *this;
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 72fac49c3f6f2..528fe9d1722be 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -107,6 +107,8 @@ RESOURCE Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void (const hlsl::[[RESOURCE]] &)'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const hlsl::[[RESOURCE]]' xvalue <NoOp>
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
@@ -135,6 +137,8 @@ RESOURCE Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *'
// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void (const hlsl::[[RESOURCE]] &)'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const hlsl::[[RESOURCE]]' xvalue <NoOp>
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
index 3cb7827e26884..0ef4b432019bb 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
@@ -33,11 +33,17 @@ void SecondEntry() {}
// Verify the constructors are alwaysinline
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
-// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer<float>::RWBuffer()(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]]
+// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer<float>::RWBuffer()({{.*}}){{.*}} [[CtorAttr:\#[0-9]+]]
+
+// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
+// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer<float>::RWBuffer(hlsl::RWBuffer<float> const&)({{.*}}){{.*}} [[CtorAttr]]
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer<float>::RWBuffer()(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]]
+// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
+// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer<float>::RWBuffer(hlsl::RWBuffer<float> const&)({{.*}}){{.*}} [[CtorAttr]]
+
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[InitAttr:\#[0-9]+]]
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
index 71ff3bf16afcc..9354ee714f86e 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl
@@ -45,7 +45,7 @@ export void foo() {
// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %[[Tmp1]], i32 0, i32 0
// CHECK-DXIL: store target("dx.RawBuffer", i8, 0, 0) %[[Handle1]], ptr %__handle, align 4
-// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue1]], ptr align 4 %[[Tmp1]], i32 4, i1 false)
+// CHECK: call void @hlsl::ByteAddressBuffer::ByteAddressBuffer(hlsl::ByteAddressBuffer const&)(ptr {{.*}} %[[RetValue1]], ptr {{.*}} %[[Tmp1]])
// Buf2 initialization part 1 - global init function that calls RWByteAddressBuffer::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
@@ -62,7 +62,7 @@ export void foo() {
// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i8_1_0t(
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %[[Tmp2]], i32 0, i32 0
// CHECK-DXIL: store target("dx.RawBuffer", i8, 1, 0) %[[Handle2]], ptr %__handle, align 4
-// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue2]], ptr align 4 %[[Tmp2]], i32 4, i1 false)
+// CHECK: call void @hlsl::RWByteAddressBuffer::RWByteAddressBuffer(hlsl::RWByteAddressBuffer const&)(ptr {{.*}} %[[RetValue2]], ptr {{.*}} %[[Tmp2]])
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// RasterizerOrderedByteAddressBuffer C1 default constructor
diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
index 47ba8bec2bfce..ca33c4220dd73 100644
--- a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl
@@ -45,7 +45,7 @@ export void foo() {
// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %[[Tmp1]], i32 0, i32 0
// CHECK-DXIL: store target("dx.TypedBuffer", float, 1, 0, 0) %[[Handle1]], ptr %__handle, align 4
-// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue1]], ptr align 4 %[[Tmp1]], i32 4, i1 false)
+// CHECK: call void @hlsl::RWBuffer<float>::RWBuffer(hlsl::RWBuffer<float> const&)(ptr {{.*}} %[[RetValue1]], ptr {{.*}} %[[Tmp1]])
// Buf2 initialization part 1 - global init function that RWBuffer<float>::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
@@ -62,7 +62,7 @@ export void foo() {
// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_1_0_0t(
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %[[Tmp2]], i32 0, i32 0
// CHECK-DXIL: store target("dx.TypedBuffer", double, 1, 0, 0) %[[Handle2]], ptr %__handle, align 4
-// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue2]], ptr align 4 %[[Tmp2]], i32 4, i1 false)
+// CHECK: call void @hlsl::RWBuffer<double>::RWBuffer(hlsl::RWBuffer<double> const&)(ptr {{.*}} %[[RetValue2]], ptr {{.*}} %[[Tmp2]])
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by RWBuffer<int> C1 default constructor
// CHECK: define void @foo()
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
index d342c8ab456e2..4f005eab5c71a 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
@@ -46,7 +46,7 @@ export void foo() {
// CHECK-DXIL-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %[[Tmp1]], i32 0, i32 0
// CHECK-DXIL: store target("dx.RawBuffer", float, 0, 0) %[[Handle1]], ptr %__handle, align 4
-// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue1]], ptr align 4 %[[Tmp1]], i32 4, i1 false)
+// CHECK: call void @hlsl::StructuredBuffer<float>::StructuredBuffer(hlsl::StructuredBuffer<float> const&)(ptr {{.*}} %[[RetValue1]], ptr {{.*}} %[[Tmp1]])
// Buf2 initialization part 1 - global init function that calls RWStructuredBuffer<float>::__createFromImplicitBinding
// CHECK: define internal void @__cxx_global_var_init.1()
@@ -63,7 +63,7 @@ export void foo() {
// CHECK-DXIL-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f32_1_0t(
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %[[Tmp2]], i32 0, i32 0
// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) %[[Handle2]], ptr %__handle, align 4
-// CHECK-DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[RetValue2]], ptr align 4 %[[Tmp2]], i32 4, i1 false)
+// CHECK: call void @hlsl::RWStructuredBuffer<float>::RWStructuredBuffer(hlsl::RWStructuredBuffer<float> const&)(ptr {{.*}} %[[RetValue2]], ptr {{.*}} %[[Tmp2]])
// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// AppendStructuredBuffer<float> C1 default constructor
>From b487a5425a564aa9ea6159f468322e24447d073c Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Fri, 12 Sep 2025 12:50:54 -0700
Subject: [PATCH 11/12] more cleanup after merge
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index a08a6fa11ce5b..ae7af61de6810 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -130,7 +130,6 @@ struct BuiltinTypeMethodBuilder {
StorageClass SC;
llvm::SmallVector<Param> Params;
llvm::SmallVector<Stmt *> StmtsList;
- llvm::SmallVector<VarDecl *> LocalVars;
// Argument placeholders, inspired by std::placeholder. These are the indices
// of arguments to forward to `callBuiltin` and other method builder methods.
@@ -145,7 +144,6 @@ struct BuiltinTypeMethodBuilder {
_2,
_3,
_4,
- LocalVar_0 = 64,
Handle = 128,
LastStmt
};
@@ -365,17 +363,6 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
}
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
- if (PH >= PlaceHolder::LocalVar_0) {
- unsigned Index = static_cast<unsigned>(PH) -
- static_cast<unsigned>(PlaceHolder::LocalVar_0);
- assert(Index < LocalVars.size() && "local var index out of range");
- VarDecl *VD = LocalVars[Index];
- return DeclRefExpr::Create(
- AST, NestedNameSpecifierLoc(), SourceLocation(), VD, false,
- DeclarationNameInfo(VD->getDeclName(), SourceLocation()), VD->getType(),
- VK_LValue);
- }
-
ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
return DeclRefExpr::Create(
AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
>From cdc85ca7822d4cab6247ebf5b83f3fd2b6ff57fe Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Fri, 12 Sep 2025 14:32:09 -0700
Subject: [PATCH 12/12] clang-format
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index ae7af61de6810..163f40fe4ec4b 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -138,15 +138,7 @@ struct BuiltinTypeMethodBuilder {
// LastStmt - refers to the last statement in the method body; referencing
// LastStmt will remove the statement from the method body since
// it will be linked from the new expression being constructed.
- enum class PlaceHolder {
- _0,
- _1,
- _2,
- _3,
- _4,
- Handle = 128,
- LastStmt
- };
+ enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128, LastStmt };
Expr *convertPlaceholder(PlaceHolder PH);
Expr *convertPlaceholder(LocalVar &Var);
More information about the llvm-commits
mailing list