@@ -57,6 +57,15 @@ CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
5757 return CD;
5858 return nullptr ;
5959}
60+
61+ // / Set up common members and attributes for buffer types
62+ static bool resourceHasCounter (const CXXRecordDecl *Decl) {
63+ StringRef Name = Decl->getName ();
64+ return Name == " RWStructuredBuffer" || Name == " AppendStructuredBuffer" ||
65+ Name == " ConsumeStructuredBuffer" ||
66+ Name == " RasterizerOrderedStructuredBuffer" ;
67+ }
68+
6069} // namespace
6170
6271// Builder for template arguments of builtin types. Used internally
@@ -138,7 +147,16 @@ struct BuiltinTypeMethodBuilder {
138147 // LastStmt - refers to the last statement in the method body; referencing
139148 // LastStmt will remove the statement from the method body since
140149 // it will be linked from the new expression being constructed.
141- enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128 , LastStmt };
150+ enum class PlaceHolder {
151+ _0,
152+ _1,
153+ _2,
154+ _3,
155+ _4,
156+ Handle = 128 ,
157+ CounterHandle,
158+ LastStmt
159+ };
142160
143161 Expr *convertPlaceholder (PlaceHolder PH);
144162 Expr *convertPlaceholder (LocalVar &Var);
@@ -178,10 +196,17 @@ struct BuiltinTypeMethodBuilder {
178196 template <typename ResourceT, typename ValueT>
179197 BuiltinTypeMethodBuilder &setHandleFieldOnResource (ResourceT ResourceRecord,
180198 ValueT HandleValue);
199+ template <typename T>
200+ BuiltinTypeMethodBuilder &
201+ accessCounterHandleFieldOnResource (T ResourceRecord);
202+ template <typename ResourceT, typename ValueT>
203+ BuiltinTypeMethodBuilder &
204+ setCounterHandleFieldOnResource (ResourceT ResourceRecord, ValueT HandleValue);
181205 template <typename T> BuiltinTypeMethodBuilder &returnValue (T ReturnValue);
182206 BuiltinTypeMethodBuilder &returnThis ();
183207 BuiltinTypeDeclBuilder &finalize ();
184208 Expr *getResourceHandleExpr ();
209+ Expr *getResourceCounterHandleExpr ();
185210
186211private:
187212 void createDecl ();
@@ -346,6 +371,8 @@ TemplateParameterListBuilder::finalizeTemplateArgs(ConceptDecl *CD) {
346371Expr *BuiltinTypeMethodBuilder::convertPlaceholder (PlaceHolder PH) {
347372 if (PH == PlaceHolder::Handle)
348373 return getResourceHandleExpr ();
374+ if (PH == PlaceHolder::CounterHandle)
375+ return getResourceCounterHandleExpr ();
349376
350377 if (PH == PlaceHolder::LastStmt) {
351378 assert (!StmtsList.empty () && " no statements in the list" );
@@ -467,6 +494,18 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
467494 OK_Ordinary);
468495}
469496
497+ Expr *BuiltinTypeMethodBuilder::getResourceCounterHandleExpr () {
498+ ensureCompleteDecl ();
499+
500+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
501+ CXXThisExpr *This = CXXThisExpr::Create (
502+ AST, SourceLocation (), Method->getFunctionObjectParameterType (), true );
503+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField ();
504+ return MemberExpr::CreateImplicit (AST, This, false , HandleField,
505+ HandleField->getType (), VK_LValue,
506+ OK_Ordinary);
507+ }
508+
470509BuiltinTypeMethodBuilder &
471510BuiltinTypeMethodBuilder::declareLocalVar (LocalVar &Var) {
472511 ensureCompleteDecl ();
@@ -583,6 +622,44 @@ BuiltinTypeMethodBuilder::setHandleFieldOnResource(ResourceT ResourceRecord,
583622 return *this ;
584623}
585624
625+ template <typename T>
626+ BuiltinTypeMethodBuilder &
627+ BuiltinTypeMethodBuilder::accessCounterHandleFieldOnResource (T ResourceRecord) {
628+ ensureCompleteDecl ();
629+
630+ Expr *ResourceExpr = convertPlaceholder (ResourceRecord);
631+
632+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
633+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField ();
634+ MemberExpr *HandleExpr = MemberExpr::CreateImplicit (
635+ AST, ResourceExpr, false , HandleField, HandleField->getType (), VK_LValue,
636+ OK_Ordinary);
637+ StmtsList.push_back (HandleExpr);
638+ return *this ;
639+ }
640+
641+ template <typename ResourceT, typename ValueT>
642+ BuiltinTypeMethodBuilder &
643+ BuiltinTypeMethodBuilder::setCounterHandleFieldOnResource (
644+ ResourceT ResourceRecord, ValueT HandleValue) {
645+ ensureCompleteDecl ();
646+
647+ Expr *ResourceExpr = convertPlaceholder (ResourceRecord);
648+ Expr *HandleValueExpr = convertPlaceholder (HandleValue);
649+
650+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
651+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField ();
652+ MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit (
653+ AST, ResourceExpr, false , HandleField, HandleField->getType (), VK_LValue,
654+ OK_Ordinary);
655+ Stmt *AssignStmt = BinaryOperator::Create (
656+ DeclBuilder.SemaRef .getASTContext (), HandleMemberExpr, HandleValueExpr,
657+ BO_Assign, HandleMemberExpr->getType (), ExprValueKind::VK_PRValue,
658+ ExprObjectKind::OK_Ordinary, SourceLocation (), FPOptionsOverride ());
659+ StmtsList.push_back (AssignStmt);
660+ return *this ;
661+ }
662+
586663template <typename T>
587664BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue (T ReturnValue) {
588665 ensureCompleteDecl ();
@@ -722,6 +799,15 @@ BuiltinTypeDeclBuilder::addMemberVariable(StringRef Name, QualType Type,
722799 return *this ;
723800}
724801
802+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMembers (
803+ ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
804+ addHandleMember (RC, IsROV, RawBuffer, Access);
805+ if (resourceHasCounter (Record)) {
806+ addCounterHandleMember (RC, IsROV, RawBuffer, Access);
807+ }
808+ return *this ;
809+ }
810+
725811BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember (
726812 ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
727813 assert (!Record->isCompleteDefinition () && " record is already complete" );
@@ -745,6 +831,30 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
745831 return *this ;
746832}
747833
834+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember (
835+ ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
836+ assert (!Record->isCompleteDefinition () && " record is already complete" );
837+
838+ ASTContext &Ctx = SemaRef.getASTContext ();
839+ TypeSourceInfo *ElementTypeInfo =
840+ Ctx.getTrivialTypeSourceInfo (getHandleElementType (), SourceLocation ());
841+
842+ // add handle member with resource type attributes
843+ QualType AttributedResTy = QualType ();
844+ SmallVector<const Attr *> Attrs = {
845+ HLSLResourceClassAttr::CreateImplicit (Ctx, RC),
846+ IsROV ? HLSLROVAttr::CreateImplicit (Ctx) : nullptr ,
847+ RawBuffer ? HLSLRawBufferAttr::CreateImplicit (Ctx) : nullptr ,
848+ ElementTypeInfo
849+ ? HLSLContainedTypeAttr::CreateImplicit (Ctx, ElementTypeInfo)
850+ : nullptr ,
851+ HLSLIsCounterAttr::CreateImplicit (Ctx)};
852+ if (CreateHLSLAttributedResourceType (SemaRef, Ctx.HLSLResourceTy , Attrs,
853+ AttributedResTy))
854+ addMemberVariable (" __counter_handle" , AttributedResTy, {}, Access);
855+ return *this ;
856+ }
857+
748858// Adds default constructor to the resource class:
749859// Resource::Resource()
750860BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor () {
@@ -848,12 +958,18 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() {
848958
849959 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
850960
851- return BuiltinTypeMethodBuilder (*this , /* Name=*/ " " , AST.VoidTy ,
852- /* IsConst=*/ false , /* IsCtor=*/ true )
853- .addParam (" other" , ConstRecordRefType)
961+ BuiltinTypeMethodBuilder MMB (*this , /* Name=*/ " " , AST.VoidTy ,
962+ /* IsConst=*/ false , /* IsCtor=*/ true );
963+ MMB .addParam (" other" , ConstRecordRefType)
854964 .accessHandleFieldOnResource (PH::_0)
855- .assign (PH::Handle, PH::LastStmt)
856- .finalize ();
965+ .assign (PH::Handle, PH::LastStmt);
966+
967+ if (getResourceCounterHandleField ()) {
968+ MMB.accessCounterHandleFieldOnResource (PH::_0).assign (PH::CounterHandle,
969+ PH::LastStmt);
970+ }
971+
972+ return MMB.finalize ();
857973}
858974
859975BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator () {
@@ -868,12 +984,17 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
868984
869985 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
870986 DeclarationName Name = AST.DeclarationNames .getCXXOperatorName (OO_Equal);
871- return BuiltinTypeMethodBuilder (*this , Name, RecordRefType)
872- .addParam (" other" , ConstRecordRefType)
987+ BuiltinTypeMethodBuilder MMB (*this , Name, RecordRefType);
988+ MMB .addParam (" other" , ConstRecordRefType)
873989 .accessHandleFieldOnResource (PH::_0)
874- .assign (PH::Handle, PH::LastStmt)
875- .returnThis ()
876- .finalize ();
990+ .assign (PH::Handle, PH::LastStmt);
991+
992+ if (getResourceCounterHandleField ()) {
993+ MMB.accessCounterHandleFieldOnResource (PH::_0).assign (PH::CounterHandle,
994+ PH::LastStmt);
995+ }
996+
997+ return MMB.returnThis ().finalize ();
877998}
878999
8791000BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators () {
@@ -909,6 +1030,13 @@ FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
9091030 return I->second ;
9101031}
9111032
1033+ FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField () const {
1034+ auto I = Fields.find (" __counter_handle" );
1035+ if (I == Fields.end ())
1036+ return nullptr ;
1037+ return I->second ;
1038+ }
1039+
9121040QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam () {
9131041 assert (Template && " record it not a template" );
9141042 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
0 commit comments