Skip to content

[HLSL] Implicit resource binding for cbuffers #139022

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 32 commits into from
May 16, 2025
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
32 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
8194951
[HLSL] Implicit binding for cbuffers
hekota May 8, 2025
bcf27e9
Handle space-only implicit binding
hekota May 8, 2025
1f997d8
clang-format
hekota May 8, 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
9eab67d
Merge branch 'users/hekota/pr138976-implicit-binding-constructor' of …
hekota May 9, 2025
4a3e4c5
revert changes to StructuredBuffers-methods-ps.hlsl
hekota May 9, 2025
03da2d1
update comment
hekota May 9, 2025
f3d9605
fix merge
hekota May 9, 2025
d4a3bcd
rename vars
hekota May 12, 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
d82236d
Merge branch 'users/hekota/pr138976-implicit-binding-constructor' int…
hekota May 14, 2025
84d710d
Merge branch 'main' into implicit-binding-cbuffers
hekota May 15, 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
11 changes: 11 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4778,6 +4778,7 @@ def HLSLResourceBinding: InheritableAttr {
RegisterType RegType;
std::optional<unsigned> SlotNumber;
unsigned SpaceNumber;
std::optional<unsigned> ImplicitBindingOrderID;

public:
void setBinding(RegisterType RT, std::optional<unsigned> SlotNum, unsigned SpaceNum) {
Expand All @@ -4799,6 +4800,16 @@ def HLSLResourceBinding: InheritableAttr {
unsigned getSpaceNumber() const {
return SpaceNumber;
}
void setImplicitBindingOrderID(uint32_t Value) {
ImplicitBindingOrderID = Value;
}
bool hasImplicitBindingOrderID() const {
return ImplicitBindingOrderID.has_value();
}
uint32_t getImplicitBindingOrderID() const {
assert(hasImplicitBindingOrderID() && "attribute does not have implicit binding order id");
return ImplicitBindingOrderID.value();
}
}];
}

Expand Down
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
48 changes: 27 additions & 21 deletions clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
Expand All @@ -42,8 +43,8 @@ using namespace llvm;
using llvm::hlsl::CBufferRowSizeInBytes;

static void initializeBufferFromBinding(CodeGenModule &CGM,
llvm::GlobalVariable *GV, unsigned Slot,
unsigned Space);
llvm::GlobalVariable *GV,
HLSLResourceBindingAttr *RBA);

namespace {

Expand Down Expand Up @@ -257,13 +258,10 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) {
emitBufferGlobalsAndMetadata(BufDecl, BufGV);

// Initialize cbuffer from binding (implicit or explicit)
const HLSLResourceBindingAttr *RBA =
BufDecl->getAttr<HLSLResourceBindingAttr>();
// FIXME: handle implicit binding if no binding attribute is found
// (llvm/llvm-project#110722)
if (RBA && RBA->hasRegisterSlot())
initializeBufferFromBinding(CGM, BufGV, RBA->getSlotNumber(),
RBA->getSpaceNumber());
HLSLResourceBindingAttr *RBA = BufDecl->getAttr<HLSLResourceBindingAttr>();
assert(RBA &&
"cbuffer/tbuffer should always have resource binding attribute");
initializeBufferFromBinding(CGM, BufGV, RBA);
}

llvm::TargetExtType *
Expand Down Expand Up @@ -539,19 +537,27 @@ static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
}

static void initializeBufferFromBinding(CodeGenModule &CGM,
llvm::GlobalVariable *GV, unsigned Slot,
unsigned Space) {
llvm::GlobalVariable *GV,
HLSLResourceBindingAttr *RBA) {
llvm::Type *Int1Ty = llvm::Type::getInt1Ty(CGM.getLLVMContext());
llvm::Value *Args[] = {
llvm::ConstantInt::get(CGM.IntTy, Space), /* reg_space */
llvm::ConstantInt::get(CGM.IntTy, Slot), /* lower_bound */
llvm::ConstantInt::get(CGM.IntTy, 1), /* range_size */
llvm::ConstantInt::get(CGM.IntTy, 0), /* index */
llvm::ConstantInt::get(Int1Ty, false) /* non-uniform */
};
initializeBuffer(CGM, GV,
CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic(),
Args);
auto *False = llvm::ConstantInt::get(Int1Ty, false);
auto *Zero = llvm::ConstantInt::get(CGM.IntTy, 0);
auto *One = llvm::ConstantInt::get(CGM.IntTy, 1);
auto *Space =
llvm::ConstantInt::get(CGM.IntTy, RBA ? RBA->getSpaceNumber() : 0);

if (RBA->hasRegisterSlot()) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

You are unconditionally dereferencing RBA here just the line before you are using conditional operator to check if RBA is nullptr. One of these lines is in error.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ping

Copy link
Collaborator

Choose a reason for hiding this comment

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

Opened issue here: #145525

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks @shafik for following up! I was planning to fix this before I left on vacation but didn't get to it.

auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber());
Intrinsic::ID Intr =
CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
initializeBuffer(CGM, GV, Intr, {Space, RegSlot, One, Zero, False});
} else {
auto *OrderID =
llvm::ConstantInt::get(CGM.IntTy, RBA->getImplicitBindingOrderID());
Intrinsic::ID Intr =
CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
initializeBuffer(CGM, GV, Intr, {OrderID, Space, One, Zero, False});
}
}

llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
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
98 changes: 76 additions & 22 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,18 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {
BufDecl->addLayoutStruct(LS);
}

static void addImplicitBindingAttrToBuffer(Sema &S, HLSLBufferDecl *BufDecl,
uint32_t ImplicitBindingOrderID) {
RegisterType RT =
BufDecl->isCBuffer() ? RegisterType::CBuffer : RegisterType::SRV;
auto *Attr =
HLSLResourceBindingAttr::CreateImplicit(S.getASTContext(), "", "0", {});
std::optional<unsigned> RegSlot;
Attr->setBinding(RT, RegSlot, 0);
Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
BufDecl->addAttr(Attr);
}

// Handle end of cbuffer/tbuffer declaration
void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) {
auto *BufDecl = cast<HLSLBufferDecl>(Dcl);
Expand All @@ -546,9 +558,17 @@ void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) {
// create buffer layout struct
createHostLayoutStructForBuffer(SemaRef, BufDecl);

if (std::none_of(Dcl->attr_begin(), Dcl->attr_end(),
[](Attr *A) { return isa<HLSLResourceBindingAttr>(A); }))
HLSLResourceBindingAttr *RBA = Dcl->getAttr<HLSLResourceBindingAttr>();
if (!RBA || !RBA->hasRegisterSlot()) {
SemaRef.Diag(Dcl->getLocation(), diag::warn_hlsl_implicit_binding);
// Use HLSLResourceBindingAttr to transfer implicit binding order_ID
// to codegen. If it does not exist, create an implicit attribute.
uint32_t OrderID = getNextImplicitBindingOrderID();
if (RBA)
RBA->setImplicitBindingOrderID(OrderID);
else
addImplicitBindingAttrToBuffer(SemaRef, BufDecl, OrderID);
}

SemaRef.PopDeclContext();
}
Expand Down Expand Up @@ -1972,6 +1992,8 @@ void SemaHLSL::ActOnEndOfTranslationUnit(TranslationUnitDecl *TU) {
HLSLBufferDecl *DefaultCBuffer = HLSLBufferDecl::CreateDefaultCBuffer(
SemaRef.getASTContext(), SemaRef.getCurLexicalContext(),
DefaultCBufferDecls);
addImplicitBindingAttrToBuffer(SemaRef, DefaultCBuffer,
getNextImplicitBindingOrderID());
SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
createHostLayoutStructForBuffer(SemaRef, DefaultCBuffer);

Expand Down Expand Up @@ -2427,6 +2449,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 +3294,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 +3307,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->hasRegisterSlot())
// FIXME: add support for implicit binding (llvm/llvm-project#110722)
return false;
if (RBA) {
if (RBA->hasRegisterSlot())
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 +3360,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)'
Loading