@@ -246,6 +246,8 @@ class BuiltinTypeDeclBuilder {
246
246
BuiltinTypeDeclBuilder &addDecrementCounterMethod ();
247
247
BuiltinTypeDeclBuilder &addHandleAccessFunction (DeclarationName &Name,
248
248
bool IsConst, bool IsRef);
249
+ BuiltinTypeDeclBuilder &addAppendMethod ();
250
+ BuiltinTypeDeclBuilder &addConsumeMethod ();
249
251
};
250
252
251
253
struct TemplateParameterListBuilder {
@@ -443,14 +445,26 @@ struct BuiltinTypeMethodBuilder {
443
445
llvm::SmallVector<Stmt *> StmtsList;
444
446
445
447
// 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 };
449
455
450
456
Expr *convertPlaceholder (PlaceHolder PH) {
451
457
if (PH == PlaceHolder::Handle)
452
458
return getResourceHandleExpr ();
453
459
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
+
454
468
ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
455
469
ParmVarDecl *ParamDecl = Method->getParamDecl (static_cast <unsigned >(PH));
456
470
return DeclRefExpr::Create (
@@ -573,17 +587,25 @@ struct BuiltinTypeMethodBuilder {
573
587
return *this ;
574
588
}
575
589
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
+ }
579
601
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 () );
587
609
StmtsList.push_back (Deref);
588
610
return *this ;
589
611
}
@@ -685,7 +707,35 @@ BuiltinTypeDeclBuilder::addHandleAccessFunction(DeclarationName &Name,
685
707
.addParam (" Index" , AST.UnsignedIntTy )
686
708
.callBuiltin (" __builtin_hlsl_resource_getpointer" , ElemPtrTy, PH::Handle,
687
709
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)
689
739
.finalizeMethod ();
690
740
}
691
741
@@ -915,6 +965,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
915
965
onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
916
966
setupBufferType (Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
917
967
/* IsROV=*/ false , /* RawBuffer=*/ true )
968
+ .addAppendMethod ()
918
969
.completeDefinition ();
919
970
});
920
971
@@ -925,6 +976,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
925
976
onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
926
977
setupBufferType (Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
927
978
/* IsROV=*/ false , /* RawBuffer=*/ true )
979
+ .addConsumeMethod ()
928
980
.completeDefinition ();
929
981
});
930
982
0 commit comments