@@ -246,6 +246,8 @@ class BuiltinTypeDeclBuilder {
246246 BuiltinTypeDeclBuilder &addDecrementCounterMethod ();
247247 BuiltinTypeDeclBuilder &addHandleAccessFunction (DeclarationName &Name,
248248 bool IsConst, bool IsRef);
249+ BuiltinTypeDeclBuilder &addAppendMethod ();
250+ BuiltinTypeDeclBuilder &addConsumeMethod ();
249251};
250252
251253struct TemplateParameterListBuilder {
@@ -443,14 +445,26 @@ struct BuiltinTypeMethodBuilder {
443445 llvm::SmallVector<Stmt *> StmtsList;
444446
445447 // Argument placeholders, inspired by std::placeholder. These are the indices
446- // of arguments to forward to `callBuiltin`, and additionally `Handle` which
447- // refers to the resource handle.
448- enum class PlaceHolder { _0, _1, _2, _3, Handle = 127 };
448+ // of arguments to forward to `callBuiltin` and other method builder methods.
449+ // Additional special values are:
450+ // Handle - refers to the resource handle.
451+ // LastStmt - refers to the last statement in the method body; referencing
452+ // LastStmt will remove the statement from the method body since
453+ // it will be linked from the new expression being constructed.
454+ enum class PlaceHolder { _0, _1, _2, _3, Handle = 128 , LastStmt };
449455
450456 Expr *convertPlaceholder (PlaceHolder PH) {
451457 if (PH == PlaceHolder::Handle)
452458 return getResourceHandleExpr ();
453459
460+ if (PH == PlaceHolder::LastStmt) {
461+ assert (!StmtsList.empty () && " no statements in the list" );
462+ Stmt *LastStmt = StmtsList.pop_back_val ();
463+ assert (isa<ValueStmt>(LastStmt) &&
464+ " last statement does not have a value" );
465+ return cast<ValueStmt>(LastStmt)->getExprStmt ();
466+ }
467+
454468 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
455469 ParmVarDecl *ParamDecl = Method->getParamDecl (static_cast <unsigned >(PH));
456470 return DeclRefExpr::Create (
@@ -573,17 +587,25 @@ struct BuiltinTypeMethodBuilder {
573587 return *this ;
574588 }
575589
576- BuiltinTypeMethodBuilder &dereference () {
577- assert (!StmtsList.empty () && " Nothing to dereference" );
578- ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
590+ template <typename TLHS, typename TRHS>
591+ BuiltinTypeMethodBuilder &assign (TLHS LHS, TRHS RHS) {
592+ Expr *LHSExpr = convertPlaceholder (LHS);
593+ Expr *RHSExpr = convertPlaceholder (RHS);
594+ Stmt *AssignStmt = BinaryOperator::Create (
595+ DeclBuilder.SemaRef .getASTContext (), LHSExpr, RHSExpr, BO_Assign,
596+ LHSExpr->getType (), ExprValueKind::VK_PRValue,
597+ ExprObjectKind::OK_Ordinary, SourceLocation (), FPOptionsOverride ());
598+ StmtsList.push_back (AssignStmt);
599+ return *this ;
600+ }
579601
580- Expr *LastExpr = dyn_cast<Expr>(StmtsList. back ());
581- assert (LastExpr && " No expression to dereference " );
582- Expr *Deref = UnaryOperator::Create (
583- AST, LastExpr, UO_Deref, LastExpr-> getType ()-> getPointeeType () ,
584- VK_PRValue, OK_Ordinary, SourceLocation (),
585- /* CanOverflow= */ false , FPOptionsOverride ());
586- StmtsList. pop_back ( );
602+ template < typename T> BuiltinTypeMethodBuilder & dereference (T Ptr) {
603+ Expr *PtrExpr = convertPlaceholder (Ptr );
604+ Expr *Deref =
605+ UnaryOperator::Create (DeclBuilder. SemaRef . getASTContext (), PtrExpr ,
606+ UO_Deref, PtrExpr-> getType ()-> getPointeeType (),
607+ VK_PRValue, OK_Ordinary, SourceLocation (),
608+ /* CanOverflow= */ false , FPOptionsOverride () );
587609 StmtsList.push_back (Deref);
588610 return *this ;
589611 }
@@ -685,7 +707,35 @@ BuiltinTypeDeclBuilder::addHandleAccessFunction(DeclarationName &Name,
685707 .addParam (" Index" , AST.UnsignedIntTy )
686708 .callBuiltin (" __builtin_hlsl_resource_getpointer" , ElemPtrTy, PH::Handle,
687709 PH::_0)
688- .dereference ()
710+ .dereference (PH::LastStmt)
711+ .finalizeMethod ();
712+ }
713+
714+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addAppendMethod () {
715+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
716+ ASTContext &AST = SemaRef.getASTContext ();
717+ QualType ElemTy = getHandleElementType ();
718+ return BuiltinTypeMethodBuilder (*this , " Append" , AST.VoidTy )
719+ .addParam (" value" , ElemTy)
720+ .callBuiltin (" __builtin_hlsl_buffer_update_counter" , AST.UnsignedIntTy ,
721+ PH::Handle, getConstantIntExpr (1 ))
722+ .callBuiltin (" __builtin_hlsl_resource_getpointer" ,
723+ AST.getPointerType (ElemTy), PH::Handle, PH::LastStmt)
724+ .dereference (PH::LastStmt)
725+ .assign (PH::LastStmt, PH::_0)
726+ .finalizeMethod ();
727+ }
728+
729+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addConsumeMethod () {
730+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
731+ ASTContext &AST = SemaRef.getASTContext ();
732+ QualType ElemTy = getHandleElementType ();
733+ return BuiltinTypeMethodBuilder (*this , " Consume" , ElemTy)
734+ .callBuiltin (" __builtin_hlsl_buffer_update_counter" , AST.UnsignedIntTy ,
735+ PH::Handle, getConstantIntExpr (-1 ))
736+ .callBuiltin (" __builtin_hlsl_resource_getpointer" ,
737+ AST.getPointerType (ElemTy), PH::Handle, PH::LastStmt)
738+ .dereference (PH::LastStmt)
689739 .finalizeMethod ();
690740}
691741
@@ -915,6 +965,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
915965 onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
916966 setupBufferType (Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
917967 /* IsROV=*/ false , /* RawBuffer=*/ true )
968+ .addAppendMethod ()
918969 .completeDefinition ();
919970 });
920971
@@ -925,6 +976,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
925976 onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
926977 setupBufferType (Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
927978 /* IsROV=*/ false , /* RawBuffer=*/ true )
979+ .addConsumeMethod ()
928980 .completeDefinition ();
929981 });
930982
0 commit comments