@@ -138,7 +138,16 @@ struct BuiltinTypeMethodBuilder {
138138 // LastStmt - refers to the last statement in the method body; referencing
139139 // LastStmt will remove the statement from the method body since
140140 // it will be linked from the new expression being constructed.
141- enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128 , LastStmt };
141+ enum class PlaceHolder {
142+ _0,
143+ _1,
144+ _2,
145+ _3,
146+ _4,
147+ Handle = 128 ,
148+ CounterHandle,
149+ LastStmt
150+ };
142151
143152 Expr *convertPlaceholder (PlaceHolder PH);
144153 Expr *convertPlaceholder (LocalVar &Var);
@@ -178,10 +187,14 @@ struct BuiltinTypeMethodBuilder {
178187 template <typename ResourceT, typename ValueT>
179188 BuiltinTypeMethodBuilder &setHandleFieldOnResource (ResourceT ResourceRecord,
180189 ValueT HandleValue);
190+ template <typename T>
191+ BuiltinTypeMethodBuilder &
192+ accessCounterHandleFieldOnResource (T ResourceRecord);
181193 template <typename T> BuiltinTypeMethodBuilder &returnValue (T ReturnValue);
182194 BuiltinTypeMethodBuilder &returnThis ();
183195 BuiltinTypeDeclBuilder &finalize ();
184196 Expr *getResourceHandleExpr ();
197+ Expr *getResourceCounterHandleExpr ();
185198
186199private:
187200 void createDecl ();
@@ -346,6 +359,8 @@ TemplateParameterListBuilder::finalizeTemplateArgs(ConceptDecl *CD) {
346359Expr *BuiltinTypeMethodBuilder::convertPlaceholder (PlaceHolder PH) {
347360 if (PH == PlaceHolder::Handle)
348361 return getResourceHandleExpr ();
362+ if (PH == PlaceHolder::CounterHandle)
363+ return getResourceCounterHandleExpr ();
349364
350365 if (PH == PlaceHolder::LastStmt) {
351366 assert (!StmtsList.empty () && " no statements in the list" );
@@ -467,6 +482,18 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
467482 OK_Ordinary);
468483}
469484
485+ Expr *BuiltinTypeMethodBuilder::getResourceCounterHandleExpr () {
486+ ensureCompleteDecl ();
487+
488+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
489+ CXXThisExpr *This = CXXThisExpr::Create (
490+ AST, SourceLocation (), Method->getFunctionObjectParameterType (), true );
491+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField ();
492+ return MemberExpr::CreateImplicit (AST, This, false , HandleField,
493+ HandleField->getType (), VK_LValue,
494+ OK_Ordinary);
495+ }
496+
470497BuiltinTypeMethodBuilder &
471498BuiltinTypeMethodBuilder::declareLocalVar (LocalVar &Var) {
472499 ensureCompleteDecl ();
@@ -583,6 +610,22 @@ BuiltinTypeMethodBuilder::setHandleFieldOnResource(ResourceT ResourceRecord,
583610 return *this ;
584611}
585612
613+ template <typename T>
614+ BuiltinTypeMethodBuilder &
615+ BuiltinTypeMethodBuilder::accessCounterHandleFieldOnResource (T ResourceRecord) {
616+ ensureCompleteDecl ();
617+
618+ Expr *ResourceExpr = convertPlaceholder (ResourceRecord);
619+
620+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
621+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField ();
622+ MemberExpr *HandleExpr = MemberExpr::CreateImplicit (
623+ AST, ResourceExpr, false , HandleField, HandleField->getType (), VK_LValue,
624+ OK_Ordinary);
625+ StmtsList.push_back (HandleExpr);
626+ return *this ;
627+ }
628+
586629template <typename T>
587630BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue (T ReturnValue) {
588631 ensureCompleteDecl ();
@@ -722,8 +765,31 @@ BuiltinTypeDeclBuilder::addMemberVariable(StringRef Name, QualType Type,
722765 return *this ;
723766}
724767
768+ BuiltinTypeDeclBuilder &
769+ BuiltinTypeDeclBuilder::addBufferHandles (ResourceClass RC, bool IsROV,
770+ bool RawBuffer, bool HasCounter,
771+ AccessSpecifier Access) {
772+ addHandleMember (RC, IsROV, RawBuffer, Access);
773+ if (HasCounter)
774+ addCounterHandleMember (RC, IsROV, RawBuffer, Access);
775+ return *this ;
776+ }
777+
725778BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember (
726779 ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
780+ return addResourceMember (" __handle" , RC, IsROV, RawBuffer,
781+ /* IsCounter=*/ false , Access);
782+ }
783+
784+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember (
785+ ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
786+ return addResourceMember (" __counter_handle" , RC, IsROV, RawBuffer,
787+ /* IsCounter=*/ true , Access);
788+ }
789+
790+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember (
791+ StringRef MemberName, ResourceClass RC, bool IsROV, bool RawBuffer,
792+ bool IsCounter, AccessSpecifier Access) {
727793 assert (!Record->isCompleteDefinition () && " record is already complete" );
728794
729795 ASTContext &Ctx = SemaRef.getASTContext ();
@@ -739,9 +805,12 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
739805 ElementTypeInfo
740806 ? HLSLContainedTypeAttr::CreateImplicit (Ctx, ElementTypeInfo)
741807 : nullptr };
808+ if (IsCounter)
809+ Attrs.push_back (HLSLIsCounterAttr::CreateImplicit (Ctx));
810+
742811 if (CreateHLSLAttributedResourceType (SemaRef, Ctx.HLSLResourceTy , Attrs,
743812 AttributedResTy))
744- addMemberVariable (" __handle " , AttributedResTy, {}, Access);
813+ addMemberVariable (MemberName , AttributedResTy, {}, Access);
745814 return *this ;
746815}
747816
@@ -844,12 +913,17 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() {
844913
845914 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
846915
847- return BuiltinTypeMethodBuilder (*this , /* Name=*/ " " , AST.VoidTy ,
848- /* IsConst=*/ false , /* IsCtor=*/ true )
849- .addParam (" other" , ConstRecordRefType)
916+ BuiltinTypeMethodBuilder MMB (*this , /* Name=*/ " " , AST.VoidTy ,
917+ /* IsConst=*/ false , /* IsCtor=*/ true );
918+ MMB .addParam (" other" , ConstRecordRefType)
850919 .accessHandleFieldOnResource (PH::_0)
851- .assign (PH::Handle, PH::LastStmt)
852- .finalize ();
920+ .assign (PH::Handle, PH::LastStmt);
921+
922+ if (getResourceCounterHandleField ())
923+ MMB.accessCounterHandleFieldOnResource (PH::_0).assign (PH::CounterHandle,
924+ PH::LastStmt);
925+
926+ return MMB.finalize ();
853927}
854928
855929BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator () {
@@ -863,12 +937,16 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
863937
864938 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
865939 DeclarationName Name = AST.DeclarationNames .getCXXOperatorName (OO_Equal);
866- return BuiltinTypeMethodBuilder (*this , Name, RecordRefType)
867- .addParam (" other" , ConstRecordRefType)
940+ BuiltinTypeMethodBuilder MMB (*this , Name, RecordRefType);
941+ MMB .addParam (" other" , ConstRecordRefType)
868942 .accessHandleFieldOnResource (PH::_0)
869- .assign (PH::Handle, PH::LastStmt)
870- .returnThis ()
871- .finalize ();
943+ .assign (PH::Handle, PH::LastStmt);
944+
945+ if (getResourceCounterHandleField ())
946+ MMB.accessCounterHandleFieldOnResource (PH::_0).assign (PH::CounterHandle,
947+ PH::LastStmt);
948+
949+ return MMB.returnThis ().finalize ();
872950}
873951
874952BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators () {
@@ -903,6 +981,14 @@ FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
903981 return I->second ;
904982}
905983
984+ FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField () const {
985+ auto I = Fields.find (" __counter_handle" );
986+ if (I == Fields.end () ||
987+ !I->second ->getType ()->isHLSLAttributedResourceType ())
988+ return nullptr ;
989+ return I->second ;
990+ }
991+
906992QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam () {
907993 assert (Template && " record it not a template" );
908994 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
0 commit comments