@@ -455,7 +455,7 @@ struct TemplateParameterListBuilder {
455455//
456456// BuiltinTypeMethodBuilder(Sema, RecordBuilder, "MethodName", ReturnType)
457457// .addParam("param_name", Type, InOutModifier)
458- // .callBuiltin("buildin_name ", { BuiltinParams } )
458+ // .callBuiltin("builtin_name ", BuiltinParams... )
459459// .finalizeMethod();
460460//
461461// The builder needs to have all of the method parameters before it can create
@@ -465,9 +465,9 @@ struct TemplateParameterListBuilder {
465465// referenced from the body building methods. Destructor or an explicit call to
466466// finalizeMethod() will complete the method definition.
467467//
468- // The callBuiltin helper method passes in the resource handle as the first
469- // argument of the builtin call. If this is not desired it takes a bool flag to
470- // disable this .
468+ // The callBuiltin helper method accepts constants via `Expr *` or placeholder
469+ // value arguments to indicate which function arguments to forward to the
470+ // builtin .
471471//
472472// If the method that is being built has a non-void return type the
473473// finalizeMethod will create a return statent with the value of the last
@@ -489,6 +489,24 @@ struct BuiltinTypeMethodBuilder {
489489 llvm::SmallVector<MethodParam> Params;
490490 llvm::SmallVector<Stmt *> StmtsList;
491491
492+ // Argument placeholders, inspired by std::placeholder. These are the indices
493+ // of arguments to forward to `callBuiltin`, and additionally `Handle` which
494+ // refers to the resource handle.
495+ enum class PlaceHolder { _0, _1, _2, _3, Handle = 127 };
496+
497+ Expr *convertPlaceholder (PlaceHolder PH) {
498+ if (PH == PlaceHolder::Handle)
499+ return getResourceHandleExpr ();
500+
501+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
502+ ParmVarDecl *ParamDecl = Method->getParamDecl (static_cast <unsigned >(PH));
503+ return DeclRefExpr::Create (
504+ AST, NestedNameSpecifierLoc (), SourceLocation (), ParamDecl, false ,
505+ DeclarationNameInfo (ParamDecl->getDeclName (), SourceLocation ()),
506+ ParamDecl->getType (), VK_PRValue);
507+ }
508+ Expr *convertPlaceholder (Expr *E) { return E; }
509+
492510public:
493511 BuiltinTypeMethodBuilder (Sema &S, BuiltinTypeDeclBuilder &DB, StringRef Name,
494512 QualType ReturnTy)
@@ -502,7 +520,10 @@ struct BuiltinTypeMethodBuilder {
502520 HLSLParamModifierAttr::Spelling Modifier =
503521 HLSLParamModifierAttr::Keyword_in) {
504522 assert (Method == nullptr && " Cannot add param, method already created" );
505- llvm_unreachable (" not yet implemented" );
523+ const IdentifierInfo &II = DeclBuilder.SemaRef .getASTContext ().Idents .get (
524+ Name, tok::TokenKind::identifier);
525+ Params.emplace_back (II, Ty, Modifier);
526+ return *this ;
506527 }
507528
508529private:
@@ -564,9 +585,10 @@ struct BuiltinTypeMethodBuilder {
564585 OK_Ordinary);
565586 }
566587
567- BuiltinTypeMethodBuilder &
568- callBuiltin (StringRef BuiltinName, ArrayRef<Expr *> CallParms,
569- bool AddResourceHandleAsFirstArg = true ) {
588+ template <typename ... Ts>
589+ BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName, Ts... ArgSpecs) {
590+ std::array<Expr *, sizeof ...(ArgSpecs)> Args{
591+ convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
570592
571593 // The first statement added to a method or access to 'this` creates the
572594 // declaration.
@@ -579,16 +601,9 @@ struct BuiltinTypeMethodBuilder {
579601 AST, NestedNameSpecifierLoc (), SourceLocation (), FD, false ,
580602 FD->getNameInfo (), FD->getType (), VK_PRValue);
581603
582- SmallVector<Expr *> NewCallParms;
583- if (AddResourceHandleAsFirstArg) {
584- NewCallParms.push_back (getResourceHandleExpr ());
585- for (auto *P : CallParms)
586- NewCallParms.push_back (P);
587- }
588-
589- Expr *Call = CallExpr::Create (
590- AST, DRE, AddResourceHandleAsFirstArg ? NewCallParms : CallParms,
591- FD->getReturnType (), VK_PRValue, SourceLocation (), FPOptionsOverride ());
604+ Expr *Call =
605+ CallExpr::Create (AST, DRE, Args, FD->getReturnType (), VK_PRValue,
606+ SourceLocation (), FPOptionsOverride ());
592607 StmtsList.push_back (Call);
593608 return *this ;
594609 }
@@ -656,18 +671,20 @@ BuiltinTypeDeclBuilder::addSimpleTemplateParams(ArrayRef<StringRef> Names,
656671}
657672
658673BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addIncrementCounterMethod () {
674+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
659675 return BuiltinTypeMethodBuilder (SemaRef, *this , " IncrementCounter" ,
660676 SemaRef.getASTContext ().UnsignedIntTy )
661- .callBuiltin (" __builtin_hlsl_buffer_update_counter" ,
662- { getConstantIntExpr (1 )} )
677+ .callBuiltin (" __builtin_hlsl_buffer_update_counter" , PH::Handle,
678+ getConstantIntExpr (1 ))
663679 .finalizeMethod ();
664680}
665681
666682BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod () {
683+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
667684 return BuiltinTypeMethodBuilder (SemaRef, *this , " DecrementCounter" ,
668685 SemaRef.getASTContext ().UnsignedIntTy )
669- .callBuiltin (" __builtin_hlsl_buffer_update_counter" ,
670- { getConstantIntExpr (-1 )} )
686+ .callBuiltin (" __builtin_hlsl_buffer_update_counter" , PH::Handle,
687+ getConstantIntExpr (-1 ))
671688 .finalizeMethod ();
672689}
673690
0 commit comments