[clang] [llvm] [HLSL] Use static create methods to initialize resources in arrays (PR #157005)
Helena Kotas via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 16 13:57:58 PDT 2025
https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/157005
>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/16] [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/16] [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/16] [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/16] 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/16] 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/16] 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/16] 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/16] 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 7e9d4c5d6757062b53c5fe99cf01636441af93af Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 4 Sep 2025 10:12:01 -0700
Subject: [PATCH 09/16] [HLSL] Use static create methods to initialize
resources in arrays
Use static methods __createFromBinding and __createFromImplicitBinding to initialize
resources in resource arrays.
Depends on #156544
Part 3 of #154221
---
clang/include/clang/Sema/SemaHLSL.h | 5 -
clang/lib/CodeGen/CGHLSLRuntime.cpp | 126 ++++++++++--------
clang/lib/Sema/SemaHLSL.cpp | 92 ++++---------
.../resources/res-array-global-dyn-index.hlsl | 9 +-
.../resources/res-array-global-multi-dim.hlsl | 28 ++--
.../res-array-global-subarray-many.hlsl | 47 ++++---
.../res-array-global-subarray-one.hlsl | 23 ++--
.../resources/res-array-global.hlsl | 43 +++---
.../hlsl_resource_handle_attrs.hlsl | 4 +-
9 files changed, 183 insertions(+), 194 deletions(-)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 5cbe1b658f5cd..86265a51fb252 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -241,11 +241,6 @@ class SemaHLSL : public SemaBase {
bool initGlobalResourceDecl(VarDecl *VD);
bool initGlobalResourceArrayDecl(VarDecl *VD);
- void createResourceRecordCtorArgs(const Type *ResourceTy, StringRef VarName,
- HLSLResourceBindingAttr *RBA,
- HLSLVkBindingAttr *VkBinding,
- uint32_t ArrayIndex,
- llvm::SmallVectorImpl<Expr *> &Args);
};
} // namespace clang
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index d27f3781c69a3..fa365f419cdb1 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "CGHLSLRuntime.h"
+#include "Address.h"
#include "CGDebugInfo.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
@@ -38,6 +39,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
#include <cstdint>
+#include <optional>
using namespace clang;
using namespace CodeGen;
@@ -148,14 +150,22 @@ static Value *buildNameForResource(llvm::StringRef BaseName,
.getPointer();
}
-static void createResourceCtorArgs(CodeGenModule &CGM, CXXConstructorDecl *CD,
- llvm::Value *ThisPtr, llvm::Value *Range,
- llvm::Value *Index, StringRef Name,
- HLSLResourceBindingAttr *RBA,
- HLSLVkBindingAttr *VkBinding,
- CallArgList &Args) {
+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;
+}
+
+static CXXMethodDecl *lookupResourceInitMethodAndSetupArgs(
+ CodeGenModule &CGM, CXXRecordDecl *ResourceDecl, llvm::Value *Range,
+ llvm::Value *Index, StringRef Name, HLSLResourceBindingAttr *RBA,
+ HLSLVkBindingAttr *VkBinding, CallArgList &Args) {
assert((VkBinding || RBA) && "at least one a binding attribute expected");
+ ASTContext &AST = CGM.getContext();
std::optional<uint32_t> RegisterSlot;
uint32_t SpaceNo = 0;
if (VkBinding) {
@@ -167,44 +177,57 @@ static void createResourceCtorArgs(CodeGenModule &CGM, CXXConstructorDecl *CD,
SpaceNo = RBA->getSpaceNumber();
}
- ASTContext &AST = CD->getASTContext();
+ CXXMethodDecl *CreateMethod = nullptr;
Value *NameStr = buildNameForResource(Name, CGM);
Value *Space = llvm::ConstantInt::get(CGM.IntTy, SpaceNo);
- Args.add(RValue::get(ThisPtr), CD->getThisType());
if (RegisterSlot.has_value()) {
// explicit binding
auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, RegisterSlot.value());
Args.add(RValue::get(RegSlot), AST.UnsignedIntTy);
- Args.add(RValue::get(Space), AST.UnsignedIntTy);
- Args.add(RValue::get(Range), AST.IntTy);
- Args.add(RValue::get(Index), AST.UnsignedIntTy);
-
+ CreateMethod = lookupMethod(ResourceDecl, "__createFromBinding", SC_Static);
} else {
// implicit binding
- assert(RBA && "missing implicit binding attribute");
auto *OrderID =
llvm::ConstantInt::get(CGM.IntTy, RBA->getImplicitBindingOrderID());
- Args.add(RValue::get(Space), AST.UnsignedIntTy);
- Args.add(RValue::get(Range), AST.IntTy);
- Args.add(RValue::get(Index), AST.UnsignedIntTy);
Args.add(RValue::get(OrderID), AST.UnsignedIntTy);
+ CreateMethod =
+ lookupMethod(ResourceDecl, "__createFromImplicitBinding", SC_Static);
}
+ Args.add(RValue::get(Space), AST.UnsignedIntTy);
+ Args.add(RValue::get(Range), AST.IntTy);
+ Args.add(RValue::get(Index), AST.UnsignedIntTy);
Args.add(RValue::get(NameStr), AST.getPointerType(AST.CharTy.withConst()));
+
+ return CreateMethod;
+}
+
+static void callResourceInitMethod(CodeGenFunction &CGF,
+ CXXMethodDecl *CreateMethod,
+ CallArgList &Args, Address ReturnAddress) {
+ llvm::Constant *CalleeFn = CGF.CGM.GetAddrOfFunction(CreateMethod);
+ const FunctionProtoType *Proto =
+ CreateMethod->getType()->getAs<FunctionProtoType>();
+ const CGFunctionInfo &FnInfo =
+ CGF.CGM.getTypes().arrangeFreeFunctionCall(Args, Proto, false);
+ ReturnValueSlot ReturnValue(ReturnAddress, false);
+ CGCallee Callee(CGCalleeInfo(Proto), CalleeFn);
+ CGF.EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr);
}
// Initializes local resource array variable. For multi-dimensional arrays it
// calls itself recursively to initialize its sub-arrays. The Index used in the
// resource constructor calls will begin at StartIndex and will be incremented
// for each array element. The last used resource Index is returned to the
-// caller.
-static Value *initializeLocalResourceArray(
- CodeGenFunction &CGF, AggValueSlot &ValueSlot,
- const ConstantArrayType *ArrayTy, CXXConstructorDecl *CD,
+// caller. If the function returns std::nullopt, it indicates an error.
+static std::optional<llvm::Value *> initializeLocalResourceArray(
+ CodeGenFunction &CGF, CXXRecordDecl *ResourceDecl,
+ const ConstantArrayType *ArrayTy, AggValueSlot &ValueSlot,
llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
HLSLResourceBindingAttr *RBA, HLSLVkBindingAttr *VkBinding,
ArrayRef<llvm::Value *> PrevGEPIndices, SourceLocation ArraySubsExprLoc) {
+ ASTContext &AST = CGF.getContext();
llvm::IntegerType *IntTy = CGF.CGM.IntTy;
llvm::Value *Index = StartIndex;
llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
@@ -225,16 +248,19 @@ static Value *initializeLocalResourceArray(
Index = CGF.Builder.CreateAdd(Index, One);
GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
}
- Index = initializeLocalResourceArray(
- CGF, ValueSlot, SubArrayTy, CD, Range, Index, ResourceName, RBA,
- VkBinding, GEPIndices, ArraySubsExprLoc);
+ std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
+ CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
+ RBA, VkBinding, GEPIndices, ArraySubsExprLoc);
+ if (!MaybeIndex)
+ return std::nullopt;
+ Index = *MaybeIndex;
}
return Index;
}
// For array of resources, initialize each resource in the array.
llvm::Type *Ty = CGF.ConvertTypeForMem(ElemType);
- CharUnits ElemSize = CD->getASTContext().getTypeSizeInChars(ElemType);
+ CharUnits ElemSize = AST.getTypeSizeInChars(ElemType);
CharUnits Align =
TmpArrayAddr.getAlignment().alignmentOfArrayElement(ElemSize);
@@ -243,16 +269,18 @@ static Value *initializeLocalResourceArray(
Index = CGF.Builder.CreateAdd(Index, One);
GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
}
- Address ThisAddress =
+ Address ReturnAddress =
CGF.Builder.CreateGEP(TmpArrayAddr, GEPIndices, Ty, Align);
- llvm::Value *ThisPtr = CGF.getAsNaturalPointerTo(ThisAddress, ElemType);
CallArgList Args;
- createResourceCtorArgs(CGF.CGM, CD, ThisPtr, Range, Index, ResourceName,
- RBA, VkBinding, Args);
- CGF.EmitCXXConstructorCall(CD, Ctor_Complete, false, false, ThisAddress,
- Args, ValueSlot.mayOverlap(), ArraySubsExprLoc,
- ValueSlot.isSanitizerChecked());
+ CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
+ CGF.CGM, ResourceDecl, Range, Index, ResourceName, RBA, VkBinding,
+ Args);
+
+ if (!CreateMethod)
+ return std::nullopt;
+
+ callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
}
return Index;
}
@@ -906,11 +934,6 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
QualType ResourceTy =
ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
- // Lookup the resource class constructor based on the resource type and
- // binding.
- CXXConstructorDecl *CD = findResourceConstructorDecl(
- AST, ResourceTy, VkBinding || RBA->hasRegisterSlot());
-
// Create a temporary variable for the result, which is either going
// to be a single resource instance or a local array of resources (we need to
// return an LValue).
@@ -923,7 +946,6 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
TmpVar, Qualifiers(), AggValueSlot::IsDestructed_t(true),
AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsAliased_t(false),
AggValueSlot::DoesNotOverlap);
- Address TmpVarAddress = ValueSlot.getAddress();
// Calculate total array size (= range size).
llvm::Value *Range =
@@ -932,27 +954,27 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
// If the result of the subscript operation is a single resource, call the
// constructor.
if (ResultTy == ResourceTy) {
- QualType ThisType = CD->getThisType()->getPointeeType();
- llvm::Value *ThisPtr = CGF.getAsNaturalPointerTo(TmpVarAddress, ThisType);
-
- // Assemble the constructor parameters.
CallArgList Args;
- createResourceCtorArgs(CGM, CD, ThisPtr, Range, Index, ArrayDecl->getName(),
- RBA, VkBinding, Args);
- // Call the constructor.
- CGF.EmitCXXConstructorCall(CD, Ctor_Complete, false, false, TmpVarAddress,
- Args, ValueSlot.mayOverlap(),
- ArraySubsExpr->getExprLoc(),
- ValueSlot.isSanitizerChecked());
+ CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
+ CGF.CGM, ResourceTy->getAsCXXRecordDecl(), Range, Index,
+ ArrayDecl->getName(), RBA, VkBinding, Args);
+
+ if (!CreateMethod)
+ return std::nullopt;
+
+ callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
+
} else {
// The result of the subscript operation is a local resource array which
// needs to be initialized.
const ConstantArrayType *ArrayTy =
cast<ConstantArrayType>(ResultTy.getTypePtr());
- initializeLocalResourceArray(CGF, ValueSlot, ArrayTy, CD, Range, Index,
- ArrayDecl->getName(), RBA, VkBinding,
- {llvm::ConstantInt::get(CGM.IntTy, 0)},
- ArraySubsExpr->getExprLoc());
+ std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
+ CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
+ ArrayDecl->getName(), RBA, VkBinding,
+ {llvm::ConstantInt::get(CGM.IntTy, 0)}, ArraySubsExpr->getExprLoc());
+ if (!EndIndex)
+ return std::nullopt;
}
return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 63ca46583a59b..e9beb3f39ae68 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3696,55 +3696,6 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {
deduceAddressSpace(VD);
}
-void SemaHLSL::createResourceRecordCtorArgs(
- const Type *ResourceTy, StringRef VarName, HLSLResourceBindingAttr *RBA,
- HLSLVkBindingAttr *VkBinding, uint32_t ArrayIndex,
- llvm::SmallVectorImpl<Expr *> &Args) {
- 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();
- }
-
- ASTContext &AST = SemaRef.getASTContext();
- uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
- uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
- IntegerLiteral *RangeSize = IntegerLiteral::Create(
- AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());
- IntegerLiteral *Index =
- IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, ArrayIndex),
- AST.UnsignedIntTy, SourceLocation());
- IntegerLiteral *Space =
- IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, SpaceNo),
- AST.UnsignedIntTy, SourceLocation());
- StringLiteral *Name = StringLiteral::Create(
- AST, VarName, StringLiteralKind::Ordinary, false,
- AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()),
- SourceLocation());
-
- // resource with explicit binding
- if (RegisterSlot.has_value()) {
- IntegerLiteral *RegSlot = IntegerLiteral::Create(
- AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.UnsignedIntTy,
- SourceLocation());
- Args.append({RegSlot, Space, RangeSize, Index, Name});
- } else {
- // resource with implicit binding
- uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID())
- ? RBA->getImplicitBindingOrderID()
- : getNextImplicitBindingOrderID();
- IntegerLiteral *OrderId =
- IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID),
- AST.UnsignedIntTy, SourceLocation());
- Args.append({Space, RangeSize, Index, OrderId, Name});
- }
-}
-
bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
assert(VD->getType()->isHLSLResourceRecord() &&
"expected resource record type");
@@ -3849,28 +3800,37 @@ bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {
// Individual resources in a resource array are not initialized here. They
// are initialized later on during codegen when the individual resources are
- // accessed. Codegen will emit a call to the resource constructor with the
- // specified array index. We need to make sure though that the constructor
+ // accessed. Codegen will emit a call to the resource initialization method
+ // with the specified array index. We need to make sure though that the method
// for the specific resource type is instantiated, so codegen can emit a call
// to it when the array element is accessed.
- SmallVector<Expr *> Args;
- QualType ResElementTy = VD->getASTContext().getBaseElementType(VD->getType());
- createResourceRecordCtorArgs(ResElementTy.getTypePtr(), VD->getName(),
- VD->getAttr<HLSLResourceBindingAttr>(),
- VD->getAttr<HLSLVkBindingAttr>(), 0, Args);
- SourceLocation Loc = VD->getLocation();
- InitializedEntity Entity =
- InitializedEntity::InitializeTemporary(ResElementTy);
- InitializationKind Kind = InitializationKind::CreateDirect(Loc, Loc, Loc);
- InitializationSequence InitSeq(SemaRef, Entity, Kind, Args);
- if (InitSeq.Failed())
+ // Find correct initialization method based on the resource binding
+ // information.
+ ASTContext &AST = SemaRef.getASTContext();
+ QualType ResElementTy = AST.getBaseElementType(VD->getType());
+ CXXRecordDecl *ResourceDecl = ResElementTy->getAsCXXRecordDecl();
+
+ HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
+ HLSLVkBindingAttr *VkBinding = VD->getAttr<HLSLVkBindingAttr>();
+ CXXMethodDecl *CreateMethod = nullptr;
+
+ if (VkBinding || (RBA && RBA->hasRegisterSlot()))
+ // Resource has explicit binding.
+ CreateMethod = lookupMethod(ResourceDecl, "__createFromBinding", SC_Static);
+ else
+ // Resource has implicit binding.
+ CreateMethod =
+ lookupMethod(ResourceDecl, "__createFromImplicitBinding", SC_Static);
+
+ if (!CreateMethod)
return false;
- // This takes care of instantiating and emitting of the constructor that will
- // be called from codegen when the array is accessed.
- ExprResult OneResInit = InitSeq.Perform(SemaRef, Entity, Kind, Args);
- return !OneResInit.isInvalid();
+ // Make sure the create method template is instantiated and emitted.
+ if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
+ SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
+ true);
+ return true;
}
// Returns true if the initialization has been handled.
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl
index 5b62452ef9844..9638fa5d77934 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl
@@ -6,10 +6,8 @@
RWBuffer<float> A[4][3] : register(u2);
RWStructuredBuffer<float> Out;
-// Make sure A[GI.x][GI.y] is translated to a RWBuffer<float> constructor call with range 12 and dynamically calculated index
-
-// NOTE:
-// Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name).
+// Make sure A[GI.x][GI.y] is translated to a RWBuffer<float>::__createFromBinding call
+// with range 12 and dynamically calculated index
// CHECK: define internal void @_Z4mainDv3_j(<3 x i32> noundef %GI)
// CHECK: %[[GI_alloca:.*]] = alloca <3 x i32>, align 16
@@ -22,7 +20,8 @@ RWStructuredBuffer<float> Out;
// CHECK: %[[GI_x:.*]] = extractelement <3 x i32> %[[GI]], i32 0
// CHECK: %[[Tmp1:.*]] = mul i32 %[[GI_x]], 3
// CHECK: %[[Index:.*]] = add i32 %[[GI_y]], %[[Tmp1]]
-// CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 2, i32 noundef 0, i32 noundef 12, i32 noundef %[[Index]], ptr noundef @A.str)
+// CHECK: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp0]],
+// CHECK-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 12, i32 noundef %[[Index]], ptr noundef @A.str)
[numthreads(4,1,1)]
void main(uint3 GI : SV_GroupThreadID) {
Out[0] = A[GI.x][GI.y][0];
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
index 8d664dad58153..e267b01947abb 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
@@ -23,24 +23,20 @@ void main() {
// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer
- // NOTE:
- // Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name).
- // For implicit binding the constructor has "jijj" in the mangled name and the arguments are (space, range_size, index, order_id, name).
- // The range_size can be -1 for unbounded arrays, and that is the only signed int in the signature.
- // The order_id argument is a sequential number that is assigned to resources with implicit binding and corresponds to the order in which
- // the resources were declared. It is needed because implicit bindings are assigned later on in an LLVM pass that needs to know the order
- // of the resource declarations.
+ // Make sure that B[3][2] is translated to a RWBuffer<float>::__createFromBinding call (u2, space0) with range 16 and index 14
+ // CHECK: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}}sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Tmp0]],
+ // CHECK-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]])
- // Make sure that B[3][2] is translated to a RWBuffer<float> constructor call for explicit binding (u2, space0) with range 16 and index 14
- // CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]])
+ // Make sure that C[1][0][3] is translated to a RWBuffer<int>::__createFromBinding call (u10, space1) with range 20 and index 13
+ // CHECK: call void @_ZN4hlsl8RWBufferIiE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align {{(4|8)}} %[[Tmp1]],
+ // CHECK-SAME: i32 noundef 10, i32 noundef 1, i32 noundef 20, i32 noundef 13, ptr noundef @[[BufC]])
- // Make sure that C[1][0][3] is translated to a RWBuffer<int> constructor call for explicit binding (u10, space1) with range 20 and index 13
- // CHECK: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 10, i32 noundef 1, i32 noundef 20, i32 noundef 13, ptr noundef @[[BufC]])
+ // Make sure that D[9][2] is translated to a RWBuffer<uint>::__createFromImplicitBinding call with range 50 and index 47
+ // CHECK: call void @_ZN4hlsl8RWBufferIjE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align {{(4|8)}} %[[Tmp2]],
+ // CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 50, i32 noundef 47, ptr noundef @[[BufD]])
- // Make sure that D[9][2] is translated to a RWBuffer<uint> constructor call for implicit binding (u18, space0) with range 50 and index 47
- // CHECK: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 0, i32 noundef 50, i32 noundef 47, i32 noundef 0, ptr noundef @[[BufD]])
-
- // Make sure that the second B[3][2] is translated to the same a RWBuffer<float> constructor call as the first B[3][2] subscript
- // CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]])
+ // Make sure that the second B[3][2] is translated to the same RWBuffer<float>::__createFromBinding call as the first B[3][2] subscript
+ // CHECK: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} writable sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Tmp3]],
+ // CHECK-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]])
Out[0] = B[3][2][0] + (float)C[1][0][3][0] + (float)D[9][2][0] + B[3][2][1];
}
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
index 254d1900cd2f1..9cb413058f463 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
@@ -17,11 +17,6 @@ float foo(RWBuffer<float> Arr[3][2]) {
return Arr[1][0][0];
}
-// NOTE:
-// - _ZN4hlsl8RWBufferIfEC1EjjijPKc is the constructor call for explicit binding
-// (has "jjij" in the mangled name) and the arguments are (register, space, range_size, index, name).
-// - _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float>
-
// CHECK: define internal void @_Z4mainj(i32 noundef %GI)
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[GI_alloca:.*]] = alloca i32, align 4
@@ -35,21 +30,27 @@ float foo(RWBuffer<float> Arr[3][2]) {
[numthreads(4,1,1)]
void main(uint GI : SV_GroupThreadID) {
// Codegen for "A[4][1]" - create local array [[Tmp0]] of size 3 x 2 and initialize
-// each element by a call to the resource constructor
+// each element by a call to RWBuffer<float>::__createFromBinding
// The resource index for A[4][1][0][0] is 102 = 4 * (4 * 3 * 2) + 1 * (3 * 2)
// (index in the resource array as if it was flattened)
// CHECK-NEXT: %[[Ptr_Tmp0_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_0_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 102, ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_0_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 102, ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Ptr_Tmp0_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_0_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 103, ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_0_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 103, ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Ptr_Tmp0_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_1_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 104, ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_1_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 104, ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Ptr_Tmp0_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_1_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 105, ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_1_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 105, ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Ptr_Tmp0_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_2_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 106, ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_2_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 106, ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Ptr_Tmp0_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_2_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 107, ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_2_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 107, ptr noundef @[[BufA]])
// After this Tmp0 values are copied to %Sub using the standard array loop initializaion
// (generated from ArrayInitLoopExpr AST node)
RWBuffer<float> Sub[3][2] = A[4][1];
@@ -62,8 +63,8 @@ void main(uint GI : SV_GroupThreadID) {
float a = Sub[2][1][0];
// Codegen for "foo(A[2][GI])" - create local array [[Tmp2]] of size 3 x 2 and initialize
-// each element by a call to the resource constructor with dynamic index, and then
-// copy-in the array as an argument of "foo"
+// each element by a call to the RWBuffer<float>::__createFromBinding with dynamic index,
+// and then copy-in the array as an argument of "foo"
// Calculate the resource index for A[2][GI][0][0] (index in the resource array as if it was flattened)
// The index is 2 * (4 * 3 * 2) + GI * (3 * 2) = 48 + GI * 6
@@ -73,32 +74,38 @@ void main(uint GI : SV_GroupThreadID) {
// A[2][GI][0][0]
// CHECK-NEXT: %[[Ptr_Tmp2_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_0_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_0]], ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_0_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_0]], ptr noundef @[[BufA]])
// A[2][GI][0][1]
// CHECK-NEXT: %[[Index_A_2_GI_0_1:.*]] = add i32 %[[Index_A_2_GI_0_0]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_0_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_1]], ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_0_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_1]], ptr noundef @[[BufA]])
// A[2][GI][1][0]
// CHECK-NEXT: %[[Index_A_2_GI_1_0:.*]] = add i32 %[[Index_A_2_GI_0_1]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_1_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_0]], ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_1_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_0]], ptr noundef @[[BufA]])
// A[2][GI][1][1]
// CHECK-NEXT: %[[Index_A_2_GI_1_1:.*]] = add i32 %[[Index_A_2_GI_1_0]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_1_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_1]], ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_1_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_1]], ptr noundef @[[BufA]])
// A[2][GI][2][0]
// CHECK-NEXT: %[[Index_A_2_GI_2_0:.*]] = add i32 %[[Index_A_2_GI_1_1]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_2_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_0]], ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_2_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_0]], ptr noundef @[[BufA]])
// A[2][GI][2][1]
// CHECK-NEXT: %[[Index_A_2_GI_2_1:.*]] = add i32 %[[Index_A_2_GI_2_0]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_2_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_1]], ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_2_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_1]], ptr noundef @[[BufA]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 24, i1 false)
// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @_Z3fooA3_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp1]])
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl
index 6f343f1282c3d..0a7745f7d0768 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl
@@ -10,11 +10,6 @@ float foo(RWBuffer<float> Arr[2]) {
return Arr[1][0];
}
-// NOTE:
-// - _ZN4hlsl8RWBufferIfEC1EjjijPKc is the constructor call for explicit binding
-// (has "jjij" in the mangled name) and the arguments are (register, space, range_size, index, name).
-// - _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float>
-
// CHECK: define internal void @_Z4mainj(i32 noundef %GI)
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[GI_alloca:.*]] = alloca i32, align 4
@@ -28,11 +23,13 @@ float foo(RWBuffer<float> Arr[2]) {
[numthreads(4,1,1)]
void main(uint GI : SV_GroupThreadID) {
// Codegen for "A[2]" - create local array [[Tmp0]] of size 2 and initialize
-// each element by a call to the resource constructor
+// each element by a call to RWBuffer<float>::__createFromBinding method
// CHECK-NEXT: %[[Ptr_Tmp0_0:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp0]], i32 0, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_0]], i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef 6, ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef 6, ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Ptr_Tmp0_1:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp0]], i32 0, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_1]], i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef 7, ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef 7, ptr noundef @[[BufA]])
// After this Tmp0 values are copied to %Sub using the standard array loop initializaion
// (generated from ArrayInitLoopExpr AST node)
RWBuffer<float> Sub[2] = A[3];
@@ -44,15 +41,17 @@ void main(uint GI : SV_GroupThreadID) {
float a = Sub[1][0];
// Codegen for "foo(A[GI])" - create local array [[Tmp2]] of size 2 and initialize
-// each element by a call to the resource constructor with dynamic index, and then
-// copy-in the array as an argument of "foo"
+// each element by a call to the RWBuffer<float>::__createFromBinding method
+// with dynamic index, and then copy-in the array as an argument of "foo"
// CHECK: %[[GI:.*]] = load i32, ptr %[[GI_alloca]], align 4
// CHECK-NEXT: %[[Index_A_GI_0:.*]] = mul i32 %[[GI]], 2
// CHECK-NEXT: %[[Ptr_Tmp2_GI_0:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_GI_0]], i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef %[[Index_A_GI_0]], ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_GI_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef %[[Index_A_GI_0]], ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Index_A_GI_1:.*]] = add i32 %[[Index_A_GI_0]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_GI_1:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_GI_1]], i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef %[[Index_A_GI_1]], ptr noundef @[[BufA]])
+// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_GI_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef %[[Index_A_GI_1]], ptr noundef @[[BufA]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 8, i1 false)
// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @_Z3fooA2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp1]])
// CHECK-NEXT: store float %[[FooReturned]], ptr %b, align 4
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
index 595ea818e913b..4618e7ecde274 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
@@ -45,31 +45,42 @@ void main() {
// the resources were declared. It is needed because implicit bindings are assigned later on in an LLVM pass that needs to know the order
// of the resource declarations.
- // Make sure A[2] is translated to a RWBuffer<float> constructor call with range 4 and index 2
+ // Make sure A[2] is translated to a RWBuffer<float>::__createFromBinding call with range 4 and index 2
// and DXIL explicit binding (u10, space1)
// and SPIR-V explicit binding (binding 12, set 2)
- // DXIL: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 10, i32 noundef 1, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
- // SPV: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 12, i32 noundef 2, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
+ // DXIL: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp0]],
+ // DXIL-SAME: i32 noundef 10, i32 noundef 1, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
+ // SPV: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 8 %[[Tmp0]],
+ // SPV-SAME: i32 noundef 12, i32 noundef 2, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
- // Make sure B[3] is translated to a RWBuffer<int> constructor call with range 5 and index 3
+ // Make sure B[3] is translated to a RWBuffer<int>::__createFromImplicitBinding call with range 5 and index 3
// and DXIL for implicit binding in space0, order id 0
// and SPIR-V explicit binding (binding 13, set 0)
- // DXIL: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 0, i32 noundef 5, i32 noundef 3, i32 noundef 0, ptr noundef @[[BufB]])
- // SPV: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 13, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
+ // DXIL: call void @_ZN4hlsl8RWBufferIiE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp1]],
+ // DXIL-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
+ // SPV: call void @_ZN4hlsl8RWBufferIiE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp1]],
+ // SPV-SAME: i32 noundef 13, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
- // Make sure C[1] is translated to a RWBuffer<int> constructor call with range 3 and index 1
- // and DXIL explicit binding (u2, space0)
+ // Make sure C[1] is translated to a RWBuffer<int>::__createFromBinding call with range 3 and index 1
+ // and DXIL explicit binding (u2, space0)
// and SPIR-V explicit binding (binding 2, set 0)
- // DXIL: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
- // SPV: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
+ // DXIL: call void @_ZN4hlsl8RWBufferIiE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp2]],
+ // DXIL-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
+ // SPV: call void @_ZN4hlsl8RWBufferIiE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp2]],
+ // SPV-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
- // Make sure D[7] is translated to a RWBuffer<double> constructor call with implicit binding
+ // Make sure D[7] is translated to a RWBuffer<double>::__createFromImplicitBinding call
// for both DXIL and SPIR-V
- // DXIL: call void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 0, i32 noundef 10, i32 noundef 7, i32 noundef 1, ptr noundef @[[BufD]])
- // SPV: call void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 0, i32 noundef 10, i32 noundef 7, i32 noundef 0, ptr noundef @[[BufD]])
+ // DXIL: call void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 4 %[[Tmp3]],
+ // DXIL-SAME: i32 noundef 1, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @D.str)
+ // SPV: call void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 8 %[[Tmp3]],
+ // SPV-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @[[BufD]])
- // Make sure E[5][0] is translated to RWBuffer<uint> constructor call with implicit binding and specified space/set 2
- // DXIL: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp4]], i32 noundef 2, i32 noundef 15, i32 noundef 5, i32 noundef 2, ptr noundef @[[BufE]])
- // SPV: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp4]], i32 noundef 2, i32 noundef 15, i32 noundef 5, i32 noundef 1, ptr noundef @[[BufE]])
+ // Make sure E[5][0] is translated to RWBuffer<uint>::__createFromImplicitBinding call
+ // for both DXIL and SPIR-V with specified space/set 2
+ // DXIL: call void @_ZN4hlsl8RWBufferIjE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 4 %[[Tmp4]],
+ // DXIL-SAME: i32 noundef 2, i32 noundef 2, i32 noundef 15, i32 noundef 5, ptr noundef @[[BufE]])
+ // SPV: call void @_ZN4hlsl8RWBufferIjE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 8 %[[Tmp4]],
+ // SPV-SAME: i32 noundef 1, i32 noundef 2, i32 noundef 15, i32 noundef 5, ptr noundef @[[BufE]])
Out[0] = A[2][0] + (float)B[3][0] + (float)C[1][0] + (float)D[7][0] + (float)E[5][0];
}
diff --git a/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl b/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl
index 36e70bc686be8..8f1aab1c94a02 100644
--- a/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl
+++ b/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl
@@ -3,7 +3,7 @@
// CHECK: ClassTemplateSpecializationDecl {{.*}} class RWBuffer definition implicit_instantiation
// CHECK: TemplateArgument type 'float'
// CHECK: BuiltinType {{.*}} 'float'
-// CHECK: FieldDecl {{.*}} implicit referenced __handle '__hlsl_resource_t
+// CHECK: FieldDecl {{.*}} implicit{{.*}} __handle '__hlsl_resource_t
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]]
RWBuffer<float> Buffer1;
@@ -12,7 +12,7 @@ RWBuffer<float> Buffer1;
// CHECK: TemplateArgument type 'vector<float, 4>'
// CHECK: ExtVectorType {{.*}} 'vector<float, 4>' 4
// CHECK: BuiltinType {{.*}} 'float'
-// CHECK: FieldDecl {{.*}} implicit referenced __handle '__hlsl_resource_t
+// CHECK: FieldDecl {{.*}} implicit{{.*}} __handle '__hlsl_resource_t
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<float, 4>)]]
>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 10/16] 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 6669bd72d95a783123844d13397fe79799a753ce Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 4 Sep 2025 20:00:33 -0700
Subject: [PATCH 11/16] Update tests to use llvm-cxxfilt to have names without
mangling
---
.../resources/res-array-global-dyn-index.hlsl | 7 ++-
.../resources/res-array-global-multi-dim.hlsl | 18 +++---
.../res-array-global-subarray-many.hlsl | 56 +++++++++++++------
.../res-array-global-subarray-one.hlsl | 20 ++++---
.../resources/res-array-global.hlsl | 46 +++++++--------
5 files changed, 89 insertions(+), 58 deletions(-)
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl
index e5acfbf6e20ab..f17cf12945e4a 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s
// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
@@ -9,7 +9,7 @@ RWStructuredBuffer<float> Out;
// Make sure A[GI.x][GI.y] is translated to a RWBuffer<float>::__createFromBinding call
// with range 12 and dynamically calculated index
-// CHECK: define internal void @_Z4mainDv3_j(<3 x i32> noundef %GI)
+// CHECK: define internal void @main(unsigned int vector[3])(<3 x i32> noundef %GI)
// CHECK: %[[GI_alloca:.*]] = alloca <3 x i32>, align 16
// CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: store <3 x i32> %GI, ptr %[[GI_alloca]]
@@ -20,7 +20,8 @@ RWStructuredBuffer<float> Out;
// CHECK: %[[GI_x:.*]] = extractelement <3 x i32> %[[GI]], i32 0
// CHECK: %[[Tmp1:.*]] = mul i32 %[[GI_x]], 3
// CHECK: %[[Index:.*]] = add i32 %[[GI_y]], %[[Tmp1]]
-// CHECK: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp0]],
+// CHECK: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp0]],
// CHECK-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 12, i32 noundef %[[Index]], ptr noundef @A.str)
[numthreads(4,1,1)]
void main(uint3 GI : SV_GroupThreadID) {
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
index be2ff87c800a4..1a05897b9e70b 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s
// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s
// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1
// CHECK: @[[BufC:.*]] = private unnamed_addr constant [2 x i8] c"C\00", align 1
@@ -17,26 +17,30 @@ RWStructuredBuffer<float> Out;
[numthreads(4,1,1)]
void main() {
- // CHECK: define internal{{.*}} void @_Z4mainv()
+ // CHECK: define internal{{.*}} void @main()
// CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer
// Make sure that B[3][2] is translated to a RWBuffer<float>::__createFromBinding call (u2, space0) with range 16 and index 14
- // CHECK: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}}sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Tmp0]],
+ // CHECK: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Tmp0]],
// CHECK-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]])
// Make sure that C[1][0][3] is translated to a RWBuffer<int>::__createFromBinding call (u10, space1) with range 20 and index 13
- // CHECK: call void @_ZN4hlsl8RWBufferIiE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align {{(4|8)}} %[[Tmp1]],
+ // CHECK: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align {{(4|8)}} %[[Tmp1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 1, i32 noundef 20, i32 noundef 13, ptr noundef @[[BufC]])
// Make sure that D[9][2] is translated to a RWBuffer<uint>::__createFromImplicitBinding call with range 50 and index 47
- // CHECK: call void @_ZN4hlsl8RWBufferIjE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align {{(4|8)}} %[[Tmp2]],
+ // CHECK: call void @hlsl::RWBuffer<unsigned int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align {{(4|8)}} %[[Tmp2]],
// CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 50, i32 noundef 47, ptr noundef @[[BufD]])
// Make sure that the second B[3][2] is translated to the same RWBuffer<float>::__createFromBinding call as the first B[3][2] subscript
- // CHECK: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} writable sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Tmp3]],
+ // CHECK: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} writable sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Tmp3]],
// CHECK-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]])
Out[0] = B[3][2][0] + (float)C[1][0][3][0] + (float)D[9][2][0] + B[3][2][1];
}
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
index 9cb413058f463..a7a37e5ccc9be 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
@@ -1,23 +1,24 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s
// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
RWBuffer<float> A[5][4][3][2] : register(u10, space2);
RWStructuredBuffer<float> Out;
-// CHECK: define {{.*}} float @_Z3fooA3_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %Arr)
+// CHECK: define {{.*}} float @foo(hlsl::RWBuffer<float> [3][2])
+// CHECK-SAME: (ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %Arr)
// CHECK-NEXT: entry:
float foo(RWBuffer<float> Arr[3][2]) {
// CHECK-NEXT: %[[Arr_1_Ptr:.*]] = getelementptr inbounds [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %Arr, i32 0, i32 1
// CHECK-NEXT: %[[Arr_1_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Arr_1_Ptr]], i32 0, i32 0
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Arr_1_0_Ptr]], i32 noundef 0)
+// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} %[[Arr_1_0_Ptr]], i32 noundef 0)
// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4
// CHECK-NEXT: ret float %[[Value]]
return Arr[1][0][0];
}
-// CHECK: define internal void @_Z4mainj(i32 noundef %GI)
+// CHECK: define internal void @main(unsigned int)(i32 noundef %GI)
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[GI_alloca:.*]] = alloca i32, align 4
// CHECK-NEXT: %Sub = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
@@ -34,30 +35,42 @@ void main(uint GI : SV_GroupThreadID) {
// The resource index for A[4][1][0][0] is 102 = 4 * (4 * 3 * 2) + 1 * (3 * 2)
// (index in the resource array as if it was flattened)
// CHECK-NEXT: %[[Ptr_Tmp0_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_0_0]],
+// 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 %[[Ptr_Tmp0_0_0]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 102, ptr noundef @[[BufA]])
+
// CHECK-NEXT: %[[Ptr_Tmp0_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_0_1]],
+// 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 %[[Ptr_Tmp0_0_1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 103, ptr noundef @[[BufA]])
+
// CHECK-NEXT: %[[Ptr_Tmp0_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_1_0]],
+// 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 %[[Ptr_Tmp0_1_0]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 104, ptr noundef @[[BufA]])
+
// CHECK-NEXT: %[[Ptr_Tmp0_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_1_1]],
+// 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 %[[Ptr_Tmp0_1_1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 105, ptr noundef @[[BufA]])
+
// CHECK-NEXT: %[[Ptr_Tmp0_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_2_0]],
+// 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 %[[Ptr_Tmp0_2_0]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 106, ptr noundef @[[BufA]])
+
// CHECK-NEXT: %[[Ptr_Tmp0_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_2_1]],
+// 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 %[[Ptr_Tmp0_2_1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 107, ptr noundef @[[BufA]])
+
// After this Tmp0 values are copied to %Sub using the standard array loop initializaion
// (generated from ArrayInitLoopExpr AST node)
RWBuffer<float> Sub[3][2] = A[4][1];
// CHECK: %[[Ptr_Sub_2:.*]] = getelementptr inbounds [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %Sub, i32 0, i32 2
// CHECK: %[[Ptr_Sub_2_1:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Ptr_Sub_2]], i32 0, i32 1
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Ptr_Sub_2_1]], i32 noundef 0)
+// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} %[[Ptr_Sub_2_1]], i32 noundef 0)
// CHECK-NEXT: %[[Sub_2_1_0_Value:.*]] = load float, ptr %[[BufPtr]], align 4
// CHECK-NEXT: store float %[[Sub_2_1_0_Value]], ptr %a, align 4
float a = Sub[2][1][0];
@@ -74,41 +87,48 @@ void main(uint GI : SV_GroupThreadID) {
// A[2][GI][0][0]
// CHECK-NEXT: %[[Ptr_Tmp2_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_0_0]],
+// 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 %[[Ptr_Tmp2_0_0]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_0]], ptr noundef @[[BufA]])
// A[2][GI][0][1]
// CHECK-NEXT: %[[Index_A_2_GI_0_1:.*]] = add i32 %[[Index_A_2_GI_0_0]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_0_1]],
+// 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 %[[Ptr_Tmp2_0_1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_1]], ptr noundef @[[BufA]])
// A[2][GI][1][0]
// CHECK-NEXT: %[[Index_A_2_GI_1_0:.*]] = add i32 %[[Index_A_2_GI_0_1]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_1_0]],
+// 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 %[[Ptr_Tmp2_1_0]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_0]], ptr noundef @[[BufA]])
// A[2][GI][1][1]
// CHECK-NEXT: %[[Index_A_2_GI_1_1:.*]] = add i32 %[[Index_A_2_GI_1_0]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_1_1]],
+// 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 %[[Ptr_Tmp2_1_1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_1]], ptr noundef @[[BufA]])
// A[2][GI][2][0]
// CHECK-NEXT: %[[Index_A_2_GI_2_0:.*]] = add i32 %[[Index_A_2_GI_1_1]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_2_0]],
+// 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 %[[Ptr_Tmp2_2_0]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_0]], ptr noundef @[[BufA]])
// A[2][GI][2][1]
// CHECK-NEXT: %[[Index_A_2_GI_2_1:.*]] = add i32 %[[Index_A_2_GI_2_0]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_2_1]],
+// 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 %[[Ptr_Tmp2_2_1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_1]], ptr noundef @[[BufA]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 24, i1 false)
-// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @_Z3fooA3_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp1]])
+// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @foo(hlsl::RWBuffer<float> [3][2])
+// CHECK-SAME: (ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp1]])
// CHECK-NEXT: store float %[[FooReturned]], ptr %b, align 4
float b = foo(A[2][GI]);
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl
index 2f256c117016d..bbd48b7ddea52 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s
// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
@@ -10,7 +10,7 @@ float foo(RWBuffer<float> Arr[2]) {
return Arr[1][0];
}
-// CHECK: define internal void @_Z4mainj(i32 noundef %GI)
+// CHECK: define internal void @main(unsigned int)(i32 noundef %GI)
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[GI_alloca:.*]] = alloca i32, align 4
// CHECK-NEXT: %Sub = alloca [2 x %"class.hlsl::RWBuffer"], align 4
@@ -25,17 +25,19 @@ void main(uint GI : SV_GroupThreadID) {
// Codegen for "A[2]" - create local array [[Tmp0]] of size 2 and initialize
// each element by a call to RWBuffer<float>::__createFromBinding method
// CHECK-NEXT: %[[Ptr_Tmp0_0:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp0]], i32 0, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_0]],
+// 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 %[[Ptr_Tmp0_0]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef 6, ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Ptr_Tmp0_1:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp0]], i32 0, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp0_1]],
+// 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 %[[Ptr_Tmp0_1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef 7, ptr noundef @[[BufA]])
// After this Tmp0 values are copied to %Sub using the standard array loop initializaion
// (generated from ArrayInitLoopExpr AST node)
RWBuffer<float> Sub[2] = A[3];
// CHECK: %[[Ptr_Sub_1:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %Sub, i32 0, i32 1
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Ptr_Sub_1]], i32 noundef 0)
+// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} %[[Ptr_Sub_1]], i32 noundef 0)
// CHECK-NEXT: %[[Sub_1_0_Value:.*]] = load float, ptr %[[BufPtr]], align 4
// CHECK-NEXT: store float %[[Sub_1_0_Value]], ptr %a, align 4
float a = Sub[1][0];
@@ -46,14 +48,16 @@ void main(uint GI : SV_GroupThreadID) {
// CHECK: %[[GI:.*]] = load i32, ptr %[[GI_alloca]], align 4
// CHECK-NEXT: %[[Index_A_GI_0:.*]] = mul i32 %[[GI]], 2
// CHECK-NEXT: %[[Ptr_Tmp2_GI_0:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 0
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_GI_0]],
+// 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 %[[Ptr_Tmp2_GI_0]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef %[[Index_A_GI_0]], ptr noundef @[[BufA]])
// CHECK-NEXT: %[[Index_A_GI_1:.*]] = add i32 %[[Index_A_GI_0]], 1
// CHECK-NEXT: %[[Ptr_Tmp2_GI_1:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 1
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Ptr_Tmp2_GI_1]],
+// 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 %[[Ptr_Tmp2_GI_1]],
// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef %[[Index_A_GI_1]], ptr noundef @[[BufA]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 8, i1 false)
-// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @_Z3fooA2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp1]])
+// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @foo(hlsl::RWBuffer<float> [2])(ptr noundef byval([2 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp1]])
// CHECK-NEXT: store float %[[FooReturned]], ptr %b, align 4
float b = foo(A[GI]);
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
index 4618e7ecde274..2f530ccaa54cf 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,DXIL
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -check-prefixes=CHECK,DXIL
// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,SPV
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -check-prefixes=CHECK,SPV
// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1
@@ -30,57 +30,59 @@ RWStructuredBuffer<float> Out;
[numthreads(4,1,1)]
void main() {
- // CHECK: define internal{{.*}} void @_Z4mainv()
+ // CHECK: define internal{{.*}} void @main()
// CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer
// CHECK: %[[Tmp4:.*]] = alloca %"class.hlsl::RWBuffer
- // NOTE:
- // Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name).
- // For implicit binding the constructor has "jijj" in the mangled name and the arguments are (space, range_size, index, order_id, name).
- // The range_size can be -1 for unbounded arrays, and that is the only signed int in the signature.
- // The order_id argument is a sequential number that is assigned to resources with implicit binding and corresponds to the order in which
- // the resources were declared. It is needed because implicit bindings are assigned later on in an LLVM pass that needs to know the order
- // of the resource declarations.
-
// Make sure A[2] is translated to a RWBuffer<float>::__createFromBinding call with range 4 and index 2
// and DXIL explicit binding (u10, space1)
// and SPIR-V explicit binding (binding 12, set 2)
- // DXIL: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp0]],
+ // DXIL: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp0]],
// DXIL-SAME: i32 noundef 10, i32 noundef 1, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
- // SPV: call void @_ZN4hlsl8RWBufferIfE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 8 %[[Tmp0]],
+ // SPV: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 8 %[[Tmp0]],
// SPV-SAME: i32 noundef 12, i32 noundef 2, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
// Make sure B[3] is translated to a RWBuffer<int>::__createFromImplicitBinding call with range 5 and index 3
// and DXIL for implicit binding in space0, order id 0
// and SPIR-V explicit binding (binding 13, set 0)
- // DXIL: call void @_ZN4hlsl8RWBufferIiE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp1]],
+ // DXIL: call void @hlsl::RWBuffer<int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp1]],
// DXIL-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
- // SPV: call void @_ZN4hlsl8RWBufferIiE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp1]],
+ // SPV: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp1]],
// SPV-SAME: i32 noundef 13, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
// Make sure C[1] is translated to a RWBuffer<int>::__createFromBinding call with range 3 and index 1
// and DXIL explicit binding (u2, space0)
// and SPIR-V explicit binding (binding 2, set 0)
- // DXIL: call void @_ZN4hlsl8RWBufferIiE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp2]],
+ // DXIL: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp2]],
// DXIL-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
- // SPV: call void @_ZN4hlsl8RWBufferIiE19__createFromBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp2]],
+ // SPV: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp2]],
// SPV-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
// Make sure D[7] is translated to a RWBuffer<double>::__createFromImplicitBinding call
// for both DXIL and SPIR-V
- // DXIL: call void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 4 %[[Tmp3]],
- // DXIL-SAME: i32 noundef 1, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @D.str)
- // SPV: call void @_ZN4hlsl8RWBufferIdE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 8 %[[Tmp3]],
+ // DXIL: call void @hlsl::RWBuffer<double>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 4 %[[Tmp3]],
+ // DXIL-SAME: i32 noundef 1, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @D.str)
+ // SPV: call void @hlsl::RWBuffer<double>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 8 %[[Tmp3]],
// SPV-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @[[BufD]])
// Make sure E[5][0] is translated to RWBuffer<uint>::__createFromImplicitBinding call
// for both DXIL and SPIR-V with specified space/set 2
- // DXIL: call void @_ZN4hlsl8RWBufferIjE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 4 %[[Tmp4]],
+ // DXIL: call void @hlsl::RWBuffer<unsigned int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 4 %[[Tmp4]],
// DXIL-SAME: i32 noundef 2, i32 noundef 2, i32 noundef 15, i32 noundef 5, ptr noundef @[[BufE]])
- // SPV: call void @_ZN4hlsl8RWBufferIjE27__createFromImplicitBindingEjjijPKc(ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 8 %[[Tmp4]],
+ // SPV: call void @hlsl::RWBuffer<unsigned int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 8 %[[Tmp4]],
// SPV-SAME: i32 noundef 1, i32 noundef 2, i32 noundef 15, i32 noundef 5, ptr noundef @[[BufE]])
Out[0] = A[2][0] + (float)B[3][0] + (float)C[1][0] + (float)D[7][0] + (float)E[5][0];
}
>From 0d1bc1200f15d2fb6a9bb849da03349b3aa0c5cf Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 4 Sep 2025 20:05:43 -0700
Subject: [PATCH 12/16] fix newlines
---
.../res-array-global-subarray-many.hlsl | 272 +++++++++---------
.../resources/res-array-global.hlsl | 176 ++++++------
2 files changed, 224 insertions(+), 224 deletions(-)
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
index a7a37e5ccc9be..036feec39f1dd 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl
@@ -1,136 +1,136 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s
-
-// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
-
-RWBuffer<float> A[5][4][3][2] : register(u10, space2);
-RWStructuredBuffer<float> Out;
-
-// CHECK: define {{.*}} float @foo(hlsl::RWBuffer<float> [3][2])
-// CHECK-SAME: (ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %Arr)
-// CHECK-NEXT: entry:
-float foo(RWBuffer<float> Arr[3][2]) {
-// CHECK-NEXT: %[[Arr_1_Ptr:.*]] = getelementptr inbounds [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %Arr, i32 0, i32 1
-// CHECK-NEXT: %[[Arr_1_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Arr_1_Ptr]], i32 0, i32 0
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} %[[Arr_1_0_Ptr]], i32 noundef 0)
-// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4
-// CHECK-NEXT: ret float %[[Value]]
- return Arr[1][0][0];
-}
-
-// CHECK: define internal void @main(unsigned int)(i32 noundef %GI)
-// CHECK-NEXT: entry:
-// CHECK-NEXT: %[[GI_alloca:.*]] = alloca i32, align 4
-// CHECK-NEXT: %Sub = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
-// CHECK-NEXT: %[[Tmp0:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
-// CHECK-NEXT: %a = alloca float, align 4
-// CHECK-NEXT: %b = alloca float, align 4
-// CHECK-NEXT: %[[Tmp1:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
-// CHECK-NEXT: %[[Tmp2:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
-// CHECK-NEXT: store i32 %GI, ptr %[[GI_alloca]], align 4
-[numthreads(4,1,1)]
-void main(uint GI : SV_GroupThreadID) {
-// Codegen for "A[4][1]" - create local array [[Tmp0]] of size 3 x 2 and initialize
-// each element by a call to RWBuffer<float>::__createFromBinding
-// The resource index for A[4][1][0][0] is 102 = 4 * (4 * 3 * 2) + 1 * (3 * 2)
-// (index in the resource array as if it was flattened)
-// CHECK-NEXT: %[[Ptr_Tmp0_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 0
-// 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 %[[Ptr_Tmp0_0_0]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 102, ptr noundef @[[BufA]])
-
-// CHECK-NEXT: %[[Ptr_Tmp0_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 1
-// 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 %[[Ptr_Tmp0_0_1]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 103, ptr noundef @[[BufA]])
-
-// CHECK-NEXT: %[[Ptr_Tmp0_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 0
-// 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 %[[Ptr_Tmp0_1_0]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 104, ptr noundef @[[BufA]])
-
-// CHECK-NEXT: %[[Ptr_Tmp0_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 1
-// 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 %[[Ptr_Tmp0_1_1]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 105, ptr noundef @[[BufA]])
-
-// CHECK-NEXT: %[[Ptr_Tmp0_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 0
-// 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 %[[Ptr_Tmp0_2_0]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 106, ptr noundef @[[BufA]])
-
-// CHECK-NEXT: %[[Ptr_Tmp0_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 1
-// 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 %[[Ptr_Tmp0_2_1]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 107, ptr noundef @[[BufA]])
-
-// After this Tmp0 values are copied to %Sub using the standard array loop initializaion
-// (generated from ArrayInitLoopExpr AST node)
- RWBuffer<float> Sub[3][2] = A[4][1];
-
-// CHECK: %[[Ptr_Sub_2:.*]] = getelementptr inbounds [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %Sub, i32 0, i32 2
-// CHECK: %[[Ptr_Sub_2_1:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Ptr_Sub_2]], i32 0, i32 1
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} %[[Ptr_Sub_2_1]], i32 noundef 0)
-// CHECK-NEXT: %[[Sub_2_1_0_Value:.*]] = load float, ptr %[[BufPtr]], align 4
-// CHECK-NEXT: store float %[[Sub_2_1_0_Value]], ptr %a, align 4
- float a = Sub[2][1][0];
-
-// Codegen for "foo(A[2][GI])" - create local array [[Tmp2]] of size 3 x 2 and initialize
-// each element by a call to the RWBuffer<float>::__createFromBinding with dynamic index,
-// and then copy-in the array as an argument of "foo"
-
-// Calculate the resource index for A[2][GI][0][0] (index in the resource array as if it was flattened)
-// The index is 2 * (4 * 3 * 2) + GI * (3 * 2) = 48 + GI * 6
-// CHECK: %[[GI:.*]] = load i32, ptr %[[GI_alloca]], align 4
-// CHECK-NEXT: %[[Index_A_2_GI_Tmp:.*]] = mul i32 %[[GI]], 6
-// CHECK-NEXT: %[[Index_A_2_GI_0_0:.*]] = add i32 %[[Index_A_2_GI_Tmp]], 48
-
-// A[2][GI][0][0]
-// CHECK-NEXT: %[[Ptr_Tmp2_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 0
-// 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 %[[Ptr_Tmp2_0_0]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_0]], ptr noundef @[[BufA]])
-
-// A[2][GI][0][1]
-// CHECK-NEXT: %[[Index_A_2_GI_0_1:.*]] = add i32 %[[Index_A_2_GI_0_0]], 1
-// CHECK-NEXT: %[[Ptr_Tmp2_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 1
-// 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 %[[Ptr_Tmp2_0_1]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_1]], ptr noundef @[[BufA]])
-
-// A[2][GI][1][0]
-// CHECK-NEXT: %[[Index_A_2_GI_1_0:.*]] = add i32 %[[Index_A_2_GI_0_1]], 1
-// CHECK-NEXT: %[[Ptr_Tmp2_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 0
-// 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 %[[Ptr_Tmp2_1_0]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_0]], ptr noundef @[[BufA]])
-
-// A[2][GI][1][1]
-// CHECK-NEXT: %[[Index_A_2_GI_1_1:.*]] = add i32 %[[Index_A_2_GI_1_0]], 1
-// CHECK-NEXT: %[[Ptr_Tmp2_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 1
-// 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 %[[Ptr_Tmp2_1_1]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_1]], ptr noundef @[[BufA]])
-
-// A[2][GI][2][0]
-// CHECK-NEXT: %[[Index_A_2_GI_2_0:.*]] = add i32 %[[Index_A_2_GI_1_1]], 1
-// CHECK-NEXT: %[[Ptr_Tmp2_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 0
-// 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 %[[Ptr_Tmp2_2_0]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_0]], ptr noundef @[[BufA]])
-
-// A[2][GI][2][1]
-// CHECK-NEXT: %[[Index_A_2_GI_2_1:.*]] = add i32 %[[Index_A_2_GI_2_0]], 1
-// CHECK-NEXT: %[[Ptr_Tmp2_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 1
-// 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 %[[Ptr_Tmp2_2_1]],
-// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_1]], ptr noundef @[[BufA]])
-
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 24, i1 false)
-// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @foo(hlsl::RWBuffer<float> [3][2])
-// CHECK-SAME: (ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp1]])
-// CHECK-NEXT: store float %[[FooReturned]], ptr %b, align 4
- float b = foo(A[2][GI]);
-
- Out[0] = a + b;
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s
+
+// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
+
+RWBuffer<float> A[5][4][3][2] : register(u10, space2);
+RWStructuredBuffer<float> Out;
+
+// CHECK: define {{.*}} float @foo(hlsl::RWBuffer<float> [3][2])
+// CHECK-SAME: (ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %Arr)
+// CHECK-NEXT: entry:
+float foo(RWBuffer<float> Arr[3][2]) {
+// CHECK-NEXT: %[[Arr_1_Ptr:.*]] = getelementptr inbounds [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %Arr, i32 0, i32 1
+// CHECK-NEXT: %[[Arr_1_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Arr_1_Ptr]], i32 0, i32 0
+// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} %[[Arr_1_0_Ptr]], i32 noundef 0)
+// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4
+// CHECK-NEXT: ret float %[[Value]]
+ return Arr[1][0][0];
+}
+
+// CHECK: define internal void @main(unsigned int)(i32 noundef %GI)
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %[[GI_alloca:.*]] = alloca i32, align 4
+// CHECK-NEXT: %Sub = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
+// CHECK-NEXT: %[[Tmp0:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
+// CHECK-NEXT: %a = alloca float, align 4
+// CHECK-NEXT: %b = alloca float, align 4
+// CHECK-NEXT: %[[Tmp1:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
+// CHECK-NEXT: %[[Tmp2:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4
+// CHECK-NEXT: store i32 %GI, ptr %[[GI_alloca]], align 4
+[numthreads(4,1,1)]
+void main(uint GI : SV_GroupThreadID) {
+// Codegen for "A[4][1]" - create local array [[Tmp0]] of size 3 x 2 and initialize
+// each element by a call to RWBuffer<float>::__createFromBinding
+// The resource index for A[4][1][0][0] is 102 = 4 * (4 * 3 * 2) + 1 * (3 * 2)
+// (index in the resource array as if it was flattened)
+// CHECK-NEXT: %[[Ptr_Tmp0_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 0
+// 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 %[[Ptr_Tmp0_0_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 102, ptr noundef @[[BufA]])
+
+// CHECK-NEXT: %[[Ptr_Tmp0_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 1
+// 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 %[[Ptr_Tmp0_0_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 103, ptr noundef @[[BufA]])
+
+// CHECK-NEXT: %[[Ptr_Tmp0_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 0
+// 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 %[[Ptr_Tmp0_1_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 104, ptr noundef @[[BufA]])
+
+// CHECK-NEXT: %[[Ptr_Tmp0_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 1
+// 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 %[[Ptr_Tmp0_1_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 105, ptr noundef @[[BufA]])
+
+// CHECK-NEXT: %[[Ptr_Tmp0_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 0
+// 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 %[[Ptr_Tmp0_2_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 106, ptr noundef @[[BufA]])
+
+// CHECK-NEXT: %[[Ptr_Tmp0_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 1
+// 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 %[[Ptr_Tmp0_2_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 107, ptr noundef @[[BufA]])
+
+// After this Tmp0 values are copied to %Sub using the standard array loop initializaion
+// (generated from ArrayInitLoopExpr AST node)
+ RWBuffer<float> Sub[3][2] = A[4][1];
+
+// CHECK: %[[Ptr_Sub_2:.*]] = getelementptr inbounds [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %Sub, i32 0, i32 2
+// CHECK: %[[Ptr_Sub_2_1:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Ptr_Sub_2]], i32 0, i32 1
+// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} %[[Ptr_Sub_2_1]], i32 noundef 0)
+// CHECK-NEXT: %[[Sub_2_1_0_Value:.*]] = load float, ptr %[[BufPtr]], align 4
+// CHECK-NEXT: store float %[[Sub_2_1_0_Value]], ptr %a, align 4
+ float a = Sub[2][1][0];
+
+// Codegen for "foo(A[2][GI])" - create local array [[Tmp2]] of size 3 x 2 and initialize
+// each element by a call to the RWBuffer<float>::__createFromBinding with dynamic index,
+// and then copy-in the array as an argument of "foo"
+
+// Calculate the resource index for A[2][GI][0][0] (index in the resource array as if it was flattened)
+// The index is 2 * (4 * 3 * 2) + GI * (3 * 2) = 48 + GI * 6
+// CHECK: %[[GI:.*]] = load i32, ptr %[[GI_alloca]], align 4
+// CHECK-NEXT: %[[Index_A_2_GI_Tmp:.*]] = mul i32 %[[GI]], 6
+// CHECK-NEXT: %[[Index_A_2_GI_0_0:.*]] = add i32 %[[Index_A_2_GI_Tmp]], 48
+
+// A[2][GI][0][0]
+// CHECK-NEXT: %[[Ptr_Tmp2_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 0
+// 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 %[[Ptr_Tmp2_0_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_0]], ptr noundef @[[BufA]])
+
+// A[2][GI][0][1]
+// CHECK-NEXT: %[[Index_A_2_GI_0_1:.*]] = add i32 %[[Index_A_2_GI_0_0]], 1
+// CHECK-NEXT: %[[Ptr_Tmp2_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 1
+// 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 %[[Ptr_Tmp2_0_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_1]], ptr noundef @[[BufA]])
+
+// A[2][GI][1][0]
+// CHECK-NEXT: %[[Index_A_2_GI_1_0:.*]] = add i32 %[[Index_A_2_GI_0_1]], 1
+// CHECK-NEXT: %[[Ptr_Tmp2_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 0
+// 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 %[[Ptr_Tmp2_1_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_0]], ptr noundef @[[BufA]])
+
+// A[2][GI][1][1]
+// CHECK-NEXT: %[[Index_A_2_GI_1_1:.*]] = add i32 %[[Index_A_2_GI_1_0]], 1
+// CHECK-NEXT: %[[Ptr_Tmp2_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 1
+// 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 %[[Ptr_Tmp2_1_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_1]], ptr noundef @[[BufA]])
+
+// A[2][GI][2][0]
+// CHECK-NEXT: %[[Index_A_2_GI_2_0:.*]] = add i32 %[[Index_A_2_GI_1_1]], 1
+// CHECK-NEXT: %[[Ptr_Tmp2_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 0
+// 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 %[[Ptr_Tmp2_2_0]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_0]], ptr noundef @[[BufA]])
+
+// A[2][GI][2][1]
+// CHECK-NEXT: %[[Index_A_2_GI_2_1:.*]] = add i32 %[[Index_A_2_GI_2_0]], 1
+// CHECK-NEXT: %[[Ptr_Tmp2_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 1
+// 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 %[[Ptr_Tmp2_2_1]],
+// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_1]], ptr noundef @[[BufA]])
+
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 24, i1 false)
+// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @foo(hlsl::RWBuffer<float> [3][2])
+// CHECK-SAME: (ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp1]])
+// CHECK-NEXT: store float %[[FooReturned]], ptr %b, align 4
+ float b = foo(A[2][GI]);
+
+ Out[0] = a + b;
+}
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
index 2f530ccaa54cf..f728c6b627b68 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global.hlsl
@@ -1,88 +1,88 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -check-prefixes=CHECK,DXIL
-// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -check-prefixes=CHECK,SPV
-
-// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
-// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1
-// CHECK: @[[BufC:.*]] = private unnamed_addr constant [2 x i8] c"C\00", align 1
-// CHECK: @[[BufD:.*]] = private unnamed_addr constant [2 x i8] c"D\00", align 1
-// CHECK: @[[BufE:.*]] = private unnamed_addr constant [2 x i8] c"E\00", align 1
-
-// different explicit binding for DXIL and SPIR-V
-[[vk::binding(12, 2)]]
-RWBuffer<float> A[4] : register(u10, space1);
-
-[[vk::binding(13)]] // SPIR-V explicit binding 13, set 0
-RWBuffer<int> B[5]; // DXIL implicit binding in space0
-
-// same explicit binding for both DXIL and SPIR-V
-// (SPIR-V takes the binding from register annotation if there is no vk::binding attribute))
-RWBuffer<int> C[3] : register(u2);
-
-// implicit binding for both DXIL and SPIR-V in space/set 0
-RWBuffer<double> D[10];
-
-// implicit binding for both DXIL and SPIR-V with specified space/set 0
-RWBuffer<uint> E[15] : register(space2);
-
-RWStructuredBuffer<float> Out;
-
-[numthreads(4,1,1)]
-void main() {
- // CHECK: define internal{{.*}} void @main()
- // CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp4:.*]] = alloca %"class.hlsl::RWBuffer
-
- // Make sure A[2] is translated to a RWBuffer<float>::__createFromBinding call with range 4 and index 2
- // and DXIL explicit binding (u10, space1)
- // and SPIR-V explicit binding (binding 12, set 2)
- // DXIL: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp0]],
- // DXIL-SAME: i32 noundef 10, i32 noundef 1, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
- // SPV: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 8 %[[Tmp0]],
- // SPV-SAME: i32 noundef 12, i32 noundef 2, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
-
- // Make sure B[3] is translated to a RWBuffer<int>::__createFromImplicitBinding call with range 5 and index 3
- // and DXIL for implicit binding in space0, order id 0
- // and SPIR-V explicit binding (binding 13, set 0)
- // DXIL: call void @hlsl::RWBuffer<int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp1]],
- // DXIL-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
- // SPV: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp1]],
- // SPV-SAME: i32 noundef 13, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
-
- // Make sure C[1] is translated to a RWBuffer<int>::__createFromBinding call with range 3 and index 1
- // and DXIL explicit binding (u2, space0)
- // and SPIR-V explicit binding (binding 2, set 0)
- // DXIL: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp2]],
- // DXIL-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
- // SPV: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp2]],
- // SPV-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
-
- // Make sure D[7] is translated to a RWBuffer<double>::__createFromImplicitBinding call
- // for both DXIL and SPIR-V
- // DXIL: call void @hlsl::RWBuffer<double>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 4 %[[Tmp3]],
- // DXIL-SAME: i32 noundef 1, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @D.str)
- // SPV: call void @hlsl::RWBuffer<double>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 8 %[[Tmp3]],
- // SPV-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @[[BufD]])
-
- // Make sure E[5][0] is translated to RWBuffer<uint>::__createFromImplicitBinding call
- // for both DXIL and SPIR-V with specified space/set 2
- // DXIL: call void @hlsl::RWBuffer<unsigned int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 4 %[[Tmp4]],
- // DXIL-SAME: i32 noundef 2, i32 noundef 2, i32 noundef 15, i32 noundef 5, ptr noundef @[[BufE]])
- // SPV: call void @hlsl::RWBuffer<unsigned int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
- // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 8 %[[Tmp4]],
- // SPV-SAME: i32 noundef 1, i32 noundef 2, i32 noundef 15, i32 noundef 5, ptr noundef @[[BufE]])
- Out[0] = A[2][0] + (float)B[3][0] + (float)C[1][0] + (float)D[7][0] + (float)E[5][0];
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -check-prefixes=CHECK,SPV
+
+// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
+// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1
+// CHECK: @[[BufC:.*]] = private unnamed_addr constant [2 x i8] c"C\00", align 1
+// CHECK: @[[BufD:.*]] = private unnamed_addr constant [2 x i8] c"D\00", align 1
+// CHECK: @[[BufE:.*]] = private unnamed_addr constant [2 x i8] c"E\00", align 1
+
+// different explicit binding for DXIL and SPIR-V
+[[vk::binding(12, 2)]]
+RWBuffer<float> A[4] : register(u10, space1);
+
+[[vk::binding(13)]] // SPIR-V explicit binding 13, set 0
+RWBuffer<int> B[5]; // DXIL implicit binding in space0
+
+// same explicit binding for both DXIL and SPIR-V
+// (SPIR-V takes the binding from register annotation if there is no vk::binding attribute))
+RWBuffer<int> C[3] : register(u2);
+
+// implicit binding for both DXIL and SPIR-V in space/set 0
+RWBuffer<double> D[10];
+
+// implicit binding for both DXIL and SPIR-V with specified space/set 0
+RWBuffer<uint> E[15] : register(space2);
+
+RWStructuredBuffer<float> Out;
+
+[numthreads(4,1,1)]
+void main() {
+ // CHECK: define internal{{.*}} void @main()
+ // CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
+ // CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer
+ // CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer
+ // CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer
+ // CHECK: %[[Tmp4:.*]] = alloca %"class.hlsl::RWBuffer
+
+ // Make sure A[2] is translated to a RWBuffer<float>::__createFromBinding call with range 4 and index 2
+ // and DXIL explicit binding (u10, space1)
+ // and SPIR-V explicit binding (binding 12, set 2)
+ // DXIL: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[Tmp0]],
+ // DXIL-SAME: i32 noundef 10, i32 noundef 1, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
+ // SPV: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 8 %[[Tmp0]],
+ // SPV-SAME: i32 noundef 12, i32 noundef 2, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
+
+ // Make sure B[3] is translated to a RWBuffer<int>::__createFromImplicitBinding call with range 5 and index 3
+ // and DXIL for implicit binding in space0, order id 0
+ // and SPIR-V explicit binding (binding 13, set 0)
+ // DXIL: call void @hlsl::RWBuffer<int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp1]],
+ // DXIL-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
+ // SPV: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp1]],
+ // SPV-SAME: i32 noundef 13, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
+
+ // Make sure C[1] is translated to a RWBuffer<int>::__createFromBinding call with range 3 and index 1
+ // and DXIL explicit binding (u2, space0)
+ // and SPIR-V explicit binding (binding 2, set 0)
+ // DXIL: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[Tmp2]],
+ // DXIL-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
+ // SPV: call void @hlsl::RWBuffer<int>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 8 %[[Tmp2]],
+ // SPV-SAME: i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
+
+ // Make sure D[7] is translated to a RWBuffer<double>::__createFromImplicitBinding call
+ // for both DXIL and SPIR-V
+ // DXIL: call void @hlsl::RWBuffer<double>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 4 %[[Tmp3]],
+ // DXIL-SAME: i32 noundef 1, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @D.str)
+ // SPV: call void @hlsl::RWBuffer<double>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.1") align 8 %[[Tmp3]],
+ // SPV-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 10, i32 noundef 7, ptr noundef @[[BufD]])
+
+ // Make sure E[5][0] is translated to RWBuffer<uint>::__createFromImplicitBinding call
+ // for both DXIL and SPIR-V with specified space/set 2
+ // DXIL: call void @hlsl::RWBuffer<unsigned int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // DXIL-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 4 %[[Tmp4]],
+ // DXIL-SAME: i32 noundef 2, i32 noundef 2, i32 noundef 15, i32 noundef 5, ptr noundef @[[BufE]])
+ // SPV: call void @hlsl::RWBuffer<unsigned int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // SPV-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.2") align 8 %[[Tmp4]],
+ // SPV-SAME: i32 noundef 1, i32 noundef 2, i32 noundef 15, i32 noundef 5, ptr noundef @[[BufE]])
+ Out[0] = A[2][0] + (float)B[3][0] + (float)C[1][0] + (float)D[7][0] + (float)E[5][0];
+}
>From 75e6b0f78f0d3c55c30e9f69bbdfa191b9b7ebf4 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 4 Sep 2025 20:26:06 -0700
Subject: [PATCH 13/16] Remove unused function
---
clang/lib/CodeGen/CGHLSLRuntime.cpp | 31 -----------------------------
1 file changed, 31 deletions(-)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index fa365f419cdb1..6e255f77d4daa 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -112,37 +112,6 @@ static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
return AST.getConstantArrayElementCount(cast<ConstantArrayType>(Ty));
}
-// Find constructor decl for a specific resource record type and binding
-// (implicit vs. explicit). The constructor has 5 parameters.
-// For explicit binding the signature is:
-// void(unsigned, unsigned, int, unsigned, const char *).
-// For implicit binding the signature is:
-// void(unsigned, int, unsigned, unsigned, const char *).
-static CXXConstructorDecl *findResourceConstructorDecl(ASTContext &AST,
- QualType ResTy,
- bool ExplicitBinding) {
- std::array<QualType, 5> ExpParmTypes = {
- AST.UnsignedIntTy, AST.UnsignedIntTy, AST.UnsignedIntTy,
- AST.UnsignedIntTy, AST.getPointerType(AST.CharTy.withConst())};
- ExpParmTypes[ExplicitBinding ? 2 : 1] = AST.IntTy;
-
- CXXRecordDecl *ResDecl = ResTy->getAsCXXRecordDecl();
- for (auto *Ctor : ResDecl->ctors()) {
- if (Ctor->getNumParams() != ExpParmTypes.size())
- continue;
- auto *ParmIt = Ctor->param_begin();
- auto ExpTyIt = ExpParmTypes.begin();
- for (; ParmIt != Ctor->param_end() && ExpTyIt != ExpParmTypes.end();
- ++ParmIt, ++ExpTyIt) {
- if ((*ParmIt)->getType() != *ExpTyIt)
- break;
- }
- if (ParmIt == Ctor->param_end())
- return Ctor;
- }
- llvm_unreachable("did not find constructor for resource class");
-}
-
static Value *buildNameForResource(llvm::StringRef BaseName,
CodeGenModule &CGM) {
llvm::SmallString<64> GlobalName = {BaseName, ".str"};
>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 14/16] 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 152471e8bec790fd9fcc81a74f72bb0d72e18fa5 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 10 Sep 2025 23:17:02 -0700
Subject: [PATCH 15/16] update unbounded resources test after merge from main
---
.../resources/res-array-global-unbounded.hlsl | 46 +++++++++++--------
1 file changed, 28 insertions(+), 18 deletions(-)
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-unbounded.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-unbounded.hlsl
index edf9ce01f72a6..6756a26bfc124 100644
--- a/clang/test/CodeGenHLSL/resources/res-array-global-unbounded.hlsl
+++ b/clang/test/CodeGenHLSL/resources/res-array-global-unbounded.hlsl
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,DXIL
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -check-prefixes=CHECK,DXIL
// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,SPV
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -check-prefixes=CHECK,SPV
// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1
@@ -15,16 +15,9 @@ float foo(RWBuffer<int> Arr[4], uint Index) {
return (float)Arr[Index][0];
}
-// NOTE:
-// - _ZN4hlsl8RWBufferIfEC1EjjijPKc is the constructor call for explicit binding for RWBuffer<float>
-// (has "jjij" in the mangled name) and the arguments are (register, space, range_size, index, name).
-// - _ZN4hlsl8RWBufferIiEC1EjijjPKc is the constructor call for implicit binding for RWBuffer<int>
-// (has "jijj" in the mangled name) and the arguments are (space, range_size, index, order_id, name).
-// - _ZN4hlsl8RWBufferIfEixEj is the subscript operator on RWBuffer<float>
-
[numthreads(4,1,1)]
void main(uint GI : SV_GroupIndex) {
- // CHECK: define internal {{.*}}void @_Z4mainj(i32 noundef %GI)
+ // CHECK: define internal{{.*}} void @main(unsigned int)(i32 noundef %GI)
// CHECK: %[[GI_alloca:.*]] = alloca i32, align 4
// CHECK-NEXT: %a = alloca float, align 4
// CHECK-NEXT: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
@@ -35,8 +28,10 @@ void main(uint GI : SV_GroupIndex) {
// Make sure A[100] is translated to a RWBuffer<float> constructor call with range -1 and index 100
// and explicit binding (u10, space1)
- // CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 10, i32 noundef 1, i32 noundef -1, i32 noundef 100, ptr noundef @A.str)
- // CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr{{.*}} @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Tmp0]], i32 noundef 0)
+ // CHECK: @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align {{(4|8)}} %[[Tmp0]],
+ // CHECK-SAME: i32 noundef 10, i32 noundef 1, i32 noundef -1, i32 noundef 100, ptr noundef @A.str)
+ // CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr{{.*}} @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} %[[Tmp0]], i32 noundef 0)
// CHECK-NEXT: %[[Value1:.*]] = load float, ptr{{.*}} %[[BufPtr]], align 4
// CHECK-NEXT: store float %[[Value1]], ptr %a, align 4
float a = A[100][0];
@@ -46,19 +41,34 @@ void main(uint GI : SV_GroupIndex) {
// (space 0, order_id 0)
// The first index is calculated from the array dimensions (unbounded x 5 x 4) and indices (2, 3)
// as 2 * 5 * 4 + 3 * 4 = 52 and the following indices are sequential.
+
// CHECK-NEXT: %[[Ptr_Tmp2_0:.*]] = getelementptr [4 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 0
- // CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Ptr_Tmp2_0]], i32 noundef 0, i32 noundef -1, i32 noundef 52, i32 noundef 0, ptr noundef @B.str)
+ // CHECK-NEXT: call void @hlsl::RWBuffer<int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Ptr_Tmp2_0]],
+ // CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef -1, i32 noundef 52, ptr noundef @[[BufB]])
+
// CHECK-NEXT: %[[Ptr_Tmp2_1:.*]] = getelementptr [4 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 1
- // CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Ptr_Tmp2_1]], i32 noundef 0, i32 noundef -1, i32 noundef 53, i32 noundef 0, ptr noundef @B.str)
+ // CHECK-NEXT: call void @hlsl::RWBuffer<int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Ptr_Tmp2_1]],
+ // CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef -1, i32 noundef 53, ptr noundef @[[BufB]])
+
// CHECK-NEXT: %[[Ptr_Tmp2_2:.*]] = getelementptr [4 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 2
- // CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Ptr_Tmp2_2]], i32 noundef 0, i32 noundef -1, i32 noundef 54, i32 noundef 0, ptr noundef @B.str)
+ // CHECK-NEXT: call void @hlsl::RWBuffer<int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Ptr_Tmp2_2]],
+ // CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef -1, i32 noundef 54, ptr noundef @[[BufB]])
+
// CHECK-NEXT: %[[Ptr_Tmp2_3:.*]] = getelementptr [4 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 3
- // CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Ptr_Tmp2_3]], i32 noundef 0, i32 noundef -1, i32 noundef 55, i32 noundef 0, ptr noundef @B.str)
+ // CHECK-NEXT: call void @hlsl::RWBuffer<int>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
+ // CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align {{(4|8)}} %[[Ptr_Tmp2_3]],
+ // CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef -1, i32 noundef 55, ptr noundef @[[BufB]])
+
// DXIL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 16, i1 false)
// SPV-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[Tmp1]], ptr align 8 %[[Tmp2]], i64 32, i1 false)
+
// CHECK-NEXT: %[[GI:.*]] = load i32, ptr %[[GI_alloca]], align 4
- // DXIL-NEXT: %[[Value2:.*]] = call {{.*}} float @_Z3fooA4_N4hlsl8RWBufferIiEEj(ptr noundef byval([4 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp1]], i32 noundef %[[GI]])
- // SPV-NEXT: %[[Value2:.*]] = call {{.*}} float @_Z3fooA4_N4hlsl8RWBufferIiEEj(ptr noundef byval([4 x %"class.hlsl::RWBuffer"]) align 8 %[[Tmp1]], i32 noundef %[[GI]])
+ // CHECK-NEXT: %[[Value2:.*]] = call {{.*}} float @foo(hlsl::RWBuffer<int> [4], unsigned int)
+ // CHECK-SAME: (ptr noundef byval([4 x %"class.hlsl::RWBuffer"]) align {{(4|8)}} %[[Tmp1]], i32 noundef %[[GI]])
+
// CHECK-NEXT: store float %[[Value2]], ptr %b, align 4
float b = foo(B[2][3], GI);
>From 886ab3c4dbb00c0305cd2d1ec3ffda192fcba29a Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 16 Sep 2025 13:17:56 -0700
Subject: [PATCH 16/16] add comment
---
clang/lib/CodeGen/CGHLSLRuntime.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 17b6492f291e8..f4e14ead90fca 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -958,6 +958,9 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
ArrayDecl->getName(), RBA, VkBinding, Args);
if (!CreateMethod)
+ // This can happen if someone creates an array of structs that looks like
+ // an HLSL resource record array but it does not have the required static
+ // create method. No binding will be generated for it.
return std::nullopt;
callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
More information about the llvm-commits
mailing list