Skip to content

[HLSL] Add resource constructor with implicit binding for global resources #138976

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
May 15, 2025
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d5685ec
[HLSL] Implement DXILResourceBindingAnalysis
hekota Apr 24, 2025
d8a4a3f
Rename DXILResourceBindingsInfo to DXILResourceBindingInfo
hekota Apr 25, 2025
d79900c
Merge branch 'main' of https://github.com/llvm/llvm-project into reso…
hekota Apr 25, 2025
c718763
Add wrapper pass
hekota Apr 26, 2025
9a70f06
update signature
hekota Apr 28, 2025
bca1bf3
code review feedback - rename flags, remove unnecessary functions, do…
hekota Apr 30, 2025
f58e2d5
[HLSL] Implementation of DXILResourceImplicitBinding pass
hekota Apr 30, 2025
b65d3bc
fix bug & update tests
hekota May 1, 2025
075e27e
Merge branch 'main' of https://github.com/llvm/llvm-project into reso…
hekota May 2, 2025
2f0aba1
Remove extra new line
hekota May 5, 2025
79c2e7b
Merge branch 'main' of https://github.com/llvm/llvm-project into impl…
hekota May 6, 2025
e9747e5
Merge branch 'main' of https://github.com/llvm/llvm-project into reso…
hekota May 6, 2025
da838a9
Merge branch 'users/hekota/pr137258-resource-binding-analysis' of htt…
hekota May 6, 2025
dfce6ce
[HLSL] Add resource constructor with implicit binding for global reso…
hekota May 7, 2025
8a27708
code review feedback - use std::optional, renames
hekota May 9, 2025
bc93994
Merge branch 'main' of https://github.com/llvm/llvm-project into impl…
hekota May 9, 2025
8142713
Merge branch 'users/hekota/pr138043-implicit-binding-pass' of https:/…
hekota May 9, 2025
4a3e4c5
revert changes to StructuredBuffers-methods-ps.hlsl
hekota May 9, 2025
fb3d516
Merge branch 'main' of https://github.com/llvm/llvm-project into impl…
hekota May 13, 2025
2ff496b
code review feedback - update comment, rename param
hekota May 14, 2025
e4369aa
Merge branch 'main' of https://github.com/llvm/llvm-project into impl…
hekota May 14, 2025
cecd1e4
simplify constructor tests
hekota May 14, 2025
cef2c3e
rename vars
hekota May 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -4819,6 +4819,12 @@ def HLSLResourceHandleFromBinding : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

def HLSLResourceHandleFromImplicitBinding : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_resource_handlefromimplicitbinding"];
let Attributes = [NoThrow];
let Prototype = "void(...)";
}

def HLSLAll : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_all"];
let Attributes = [NoThrow, Const];
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,20 @@ class SemaHLSL : public SemaBase {
// buffer which will be created at the end of the translation unit.
llvm::SmallVector<Decl *> DefaultCBufferDecls;

uint32_t ImplicitBindingNextOrderID = 0;

private:
void collectResourceBindingsOnVarDecl(VarDecl *D);
void collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
const RecordType *RT);
void processExplicitBindingsOnDecl(VarDecl *D);

void diagnoseAvailabilityViolations(TranslationUnitDecl *TU);

bool initGlobalResourceDecl(VarDecl *VD);
uint32_t getNextImplicitBindingOrderID() {
return ImplicitBindingNextOrderID++;
}
};

} // namespace clang
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CGHLSLBuiltins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
HandleTy, CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic(),
ArrayRef<Value *>{SpaceOp, RegisterOp, RangeOp, IndexOp, NonUniform});
}
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));
// FIXME: NonUniformResourceIndex bit is not yet implemented
// (llvm/llvm-project#135452)
Value *NonUniform =
llvm::ConstantInt::get(llvm::Type::getInt1Ty(getLLVMContext()), false);
return Builder.CreateIntrinsic(
HandleTy,
CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic(),
ArrayRef<Value *>{OrderID, SpaceOp, RangeOp, IndexOp, NonUniform});
}
case Builtin::BI__builtin_hlsl_all: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ class CGHLSLRuntime {
resource_getpointer)
GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding,
resource_handlefrombinding)
GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromImplicitBinding,
resource_handlefromimplicitbinding)
GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)
GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,
group_memory_barrier_with_group_sync)
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,26 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromBinding() {
.finalize();
}

BuiltinTypeDeclBuilder &
BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
if (Record->isCompleteDefinition())
return *this;

using PH = BuiltinTypeMethodBuilder::PlaceHolder;
ASTContext &AST = SemaRef.getASTContext();
QualType HandleType = getResourceHandleField()->getType();

return BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true)
.addParam("spaceNo", AST.UnsignedIntTy)
.addParam("range", AST.IntTy)
.addParam("index", AST.UnsignedIntTy)
.addParam("order_id", AST.UnsignedIntTy)
.callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
HandleType, PH::Handle, PH::_0, PH::_1, PH::_2, PH::_3)
.assign(PH::Handle, PH::LastStmt)
.finalize();
}

BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
ASTContext &AST = Record->getASTContext();
DeclarationName Subscript =
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ class BuiltinTypeDeclBuilder {
AccessSpecifier Access = AccessSpecifier::AS_private);
BuiltinTypeDeclBuilder &addArraySubscriptOperators();

// Builtin types methods
// Builtin types constructors
BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();

// Builtin types methods
BuiltinTypeDeclBuilder &addLoadMethods();
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
return BuiltinTypeDeclBuilder(S, Decl)
.addHandleMember(RC, IsROV, RawBuffer)
.addDefaultHandleConstructor()
.addHandleConstructorFromBinding();
.addHandleConstructorFromBinding()
.addHandleConstructorFromImplicitBinding();
}

// This function is responsible for constructing the constraint expression for
Expand Down
72 changes: 52 additions & 20 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2427,6 +2427,20 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
TheCall->setType(ResourceTy);
break;
}
case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
ASTContext &AST = SemaRef.getASTContext();
if (SemaRef.checkArgCount(TheCall, 5) ||
CheckResourceHandle(&SemaRef, TheCall, 0) ||
CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.IntTy) ||
CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.UnsignedIntTy) ||
CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy))
return true;
// use the type of the handle (arg0) as a return type
QualType ResourceTy = TheCall->getArg(0)->getType();
TheCall->setType(ResourceTy);
break;
}
case Builtin::BI__builtin_hlsl_and:
case Builtin::BI__builtin_hlsl_or: {
if (SemaRef.checkArgCount(TheCall, 2))
Expand Down Expand Up @@ -3258,8 +3272,10 @@ static bool initVarDeclWithCtor(Sema &S, VarDecl *VD,
VD->getLocation(), SourceLocation(), SourceLocation());

InitializationSequence InitSeq(S, Entity, Kind, Args);
ExprResult Init = InitSeq.Perform(S, Entity, Kind, Args);
if (InitSeq.Failed())
return false;

ExprResult Init = InitSeq.Perform(S, Entity, Kind, Args);
if (!Init.get())
return false;

Expand All @@ -3269,27 +3285,42 @@ static bool initVarDeclWithCtor(Sema &S, VarDecl *VD,
return true;
}

static bool initGlobalResourceDecl(Sema &S, VarDecl *VD) {
bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
std::optional<uint32_t> RegisterSlot;
uint32_t SpaceNo = 0;
HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
if (!RBA || RBA->isImplicit())
// FIXME: add support for implicit binding (llvm/llvm-project#110722)
return false;
if (RBA) {
if (!RBA->isImplicit())
RegisterSlot = RBA->getSlotNumber();
SpaceNo = RBA->getSpaceNumber();
}

ASTContext &AST = S.getASTContext();
ASTContext &AST = SemaRef.getASTContext();
uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
Expr *Args[] = {
IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, RBA->getSlotNumber()),
AST.UnsignedIntTy, SourceLocation()),
IntegerLiteral::Create(AST,
llvm::APInt(UIntTySize, RBA->getSpaceNumber()),
AST.UnsignedIntTy, SourceLocation()),
IntegerLiteral::Create(AST, llvm::APInt(IntTySize, 1), AST.IntTy,
SourceLocation()),
IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy,
SourceLocation())};

return initVarDeclWithCtor(S, VD, Args);
IntegerLiteral *One = IntegerLiteral::Create(AST, llvm::APInt(IntTySize, 1),
AST.IntTy, SourceLocation());
IntegerLiteral *Zero = IntegerLiteral::Create(
AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());
IntegerLiteral *Space =
IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, SpaceNo),
AST.UnsignedIntTy, SourceLocation());

// resource with explicit binding
if (RegisterSlot.has_value()) {
IntegerLiteral *RegSlot = IntegerLiteral::Create(
AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.UnsignedIntTy,
SourceLocation());
Expr *Args[] = {RegSlot, Space, One, Zero};
return initVarDeclWithCtor(SemaRef, VD, Args);
}

// resource with explicit binding
IntegerLiteral *OrderId = IntegerLiteral::Create(
AST, llvm::APInt(UIntTySize, getNextImplicitBindingOrderID()),
AST.UnsignedIntTy, SourceLocation());
Expr *Args[] = {Space, One, Zero, OrderId};
return initVarDeclWithCtor(SemaRef, VD, Args);
}

// Returns true if the initialization has been handled.
Expand All @@ -3307,8 +3338,9 @@ bool SemaHLSL::ActOnUninitializedVarDecl(VarDecl *VD) {
// FIXME: We currectly support only simple resources - no arrays of resources
// or resources in user defined structs.
// (llvm/llvm-project#133835, llvm/llvm-project#133837)
if (VD->getType()->isHLSLResourceRecord())
return initGlobalResourceDecl(SemaRef, VD);
// Initialize resources at the global scope
if (VD->hasGlobalStorage() && VD->getType()->isHLSLResourceRecord())
return initGlobalResourceDecl(VD);

return false;
}
Expand Down
22 changes: 22 additions & 0 deletions clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,27 @@ RESOURCE Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr

// Constructor from implicit binding

// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (unsigned int, int, unsigned int, unsigned int)' inline
// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
// CHECK-NEXT: ParmVarDecl {{.*}} order_id 'unsigned int'
// CHECK-NEXT: CompoundStmt {{.*}}
// CHECK-NEXT: BinaryOperator {{.*}} '='
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t
// CHECK-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
// 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 {{.*}} '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 {{.*}} 'order_id' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr

// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const element_type &(unsigned int) const'
// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'element_type &(unsigned int)'
22 changes: 22 additions & 0 deletions clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,28 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr

// Constructor from implicit binding

// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (unsigned int, int, unsigned int, unsigned int)' inline
// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
// CHECK-NEXT: ParmVarDecl {{.*}} order_id 'unsigned int'
// CHECK-NEXT: CompoundStmt {{.*}}
// CHECK-NEXT: BinaryOperator {{.*}} '='
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t
// CHECK-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding'
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]<element_type>' lvalue implicit this
// 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 {{.*}} 'order_id' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr

// Subscript operators

// CHECK-SUBSCRIPT: CXXMethodDecl {{.*}} operator[] 'const hlsl_device element_type &(unsigned int) const'
Expand Down
22 changes: 22 additions & 0 deletions clang/test/AST/HLSL/TypedBuffers-AST.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,28 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr

// Constructor from implicit binding

// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (unsigned int, int, unsigned int, unsigned int)' inline
// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
// CHECK-NEXT: ParmVarDecl {{.*}} order_id 'unsigned int'
// CHECK-NEXT: CompoundStmt {{.*}}
// CHECK-NEXT: BinaryOperator {{.*}} '='
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t
// CHECK-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding'
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]<element_type>' lvalue implicit this
// 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 {{.*}} 'order_id' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr

// Subsctript operators

// CHECK: CXXMethodDecl {{.*}} operator[] 'const hlsl_device element_type &(unsigned int) const'
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void SecondEntry() {}

// Verify the constructor is alwaysinline
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
// NOINLINE-NEXT: define linkonce_odr void @_ZN4hlsl8RWBufferIfEC2Ev({{.*}} [[CtorAttr:\#[0-9]+]]
// NOINLINE-NEXT: define linkonce_odr void @_ZN4hlsl8RWBufferIfEC2Ejijj({{.*}} [[CtorAttr:\#[0-9]+]]
Copy link
Member Author

@hekota hekota May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is changing the RWBuffer<float> Buffer; initialization from the default constructor (init handle to poison value) to the constructor with implicit binding. Then jijj suffix is Itanium mangling of the constructor arguments (unsigned int, int, unsigned int, unsigned int).


// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[InitAttr:\#[0-9]+]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,33 @@ export void foo() {
// CHECK-SAME: i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3)
// CHECK-NEXT: ret void

// Buf2 initialization part 1 - FIXME: constructor with implicit binding does not exist yet;
// the global init function currently calls the default RWByteAddressBuffer C1 constructor
// CHECK: define internal void @__cxx_global_var_init.1()
// Buf2 initialization part 1 - global init function that calls RWByteAddressBuffer C1 constructor with implicit binding
// CHECK: define internal void @__cxx_global_var_init.1() #0 {
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @_ZN4hlsl19RWByteAddressBufferC1Ev(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf2)
// CHECK-NEXT: call void @_ZN4hlsl19RWByteAddressBufferC1Ejijj(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf2,
// CHECK-SAME: i32 noundef 0, i32 noundef 1, i32 noundef 0, i32 noundef 0)

// Buf2 initialization part 2 - body of RWByteAddressBuffer C1 constructor with implicit binding that calls the C2 constructor
// CHECK: define linkonce_odr void @_ZN4hlsl19RWByteAddressBufferC1Ejijj(ptr noundef nonnull align 4 dereferenceable(4) %this,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %order_id)
// CHECK-NEXT: entry:
// CHECK-NEXT: %this.addr = alloca ptr, align 4
// CHECK-NEXT: %spaceNo.addr = alloca i32, align 4
// CHECK-NEXT: %range.addr = alloca i32, align 4
// CHECK-NEXT: %index.addr = alloca i32, align 4
// CHECK-NEXT: %order_id.addr = alloca i32, align 4
// CHECK-NEXT: store ptr %this, ptr %this.addr, align 4
// CHECK-NEXT: store i32 %spaceNo, ptr %spaceNo.addr, align 4
// CHECK-NEXT: store i32 %range, ptr %range.addr, align 4
// CHECK-NEXT: store i32 %index, ptr %index.addr, align 4
// CHECK-NEXT: store i32 %order_id, ptr %order_id.addr, align 4
// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 4
// CHECK-NEXT: %0 = load i32, ptr %spaceNo.addr, align 4
// CHECK-NEXT: %1 = load i32, ptr %range.addr, align 4
// CHECK-NEXT: %2 = load i32, ptr %index.addr, align 4
// CHECK-NEXT: %3 = load i32, ptr %order_id.addr, align 4
// CHECK-NEXT: call void @_ZN4hlsl19RWByteAddressBufferC2Ejijj(ptr noundef nonnull align 4 dereferenceable(4) %this1, i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3) #4
// CHECK-NEXT: ret void

// Buf3 initialization part 1 - local variable declared in function foo() is initialized by
// RasterizerOrderedByteAddressBuffer C1 default constructor
Expand Down Expand Up @@ -104,6 +126,31 @@ export void foo() {
// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %4, ptr %__handle, align 4
// CHECK-NEXT: ret void

// Buf2 initialization part 3 - body of RWByteAddressBuffer C2 constructor with implicit binding that initializes
// handle with @llvm.dx.resource.handlefromimplicitbinding
// CHECK: define linkonce_odr void @_ZN4hlsl19RWByteAddressBufferC2Ejijj(ptr noundef nonnull align 4 dereferenceable(4) %this,
// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %order_id) unnamed_addr #1 align 2 {
// CHECK-NEXT: entry:
// CHECK-NEXT: %this.addr = alloca ptr, align 4
// CHECK-NEXT: %spaceNo.addr = alloca i32, align 4
// CHECK-NEXT: %range.addr = alloca i32, align 4
// CHECK-NEXT: %index.addr = alloca i32, align 4
// CHECK-NEXT: %order_id.addr = alloca i32, align 4
// CHECK-NEXT: store ptr %this, ptr %this.addr, align 4
// CHECK-NEXT: store i32 %spaceNo, ptr %spaceNo.addr, align 4
// CHECK-NEXT: store i32 %range, ptr %range.addr, align 4
// CHECK-NEXT: store i32 %index, ptr %index.addr, align 4
// CHECK-NEXT: store i32 %order_id, ptr %order_id.addr, align 4
// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 4
// CHECK-NEXT: %0 = load i32, ptr %spaceNo.addr, align 4
// CHECK-NEXT: %1 = load i32, ptr %range.addr, align 4
// CHECK-NEXT: %2 = load i32, ptr %index.addr, align 4
// CHECK-NEXT: %3 = load i32, ptr %order_id.addr, align 4
// CHECK-NEXT: %4 = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i8_1_0t(i32 %3, i32 %0, i32 %1, i32 %2, i1 false)
// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %this1, i32 0, i32 0
// CHECK-NEXT: store target("dx.RawBuffer", i8, 1, 0) %4, ptr %__handle, align 4
// CHECK-NEXT: ret void

// Buf3 initialization part 3 - body of RasterizerOrderedByteAddressBuffer default C2 constructor that
// initializes handle to poison
// CHECK: define linkonce_odr void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
Expand Down
Loading