1919#include " clang/AST/Expr.h"
2020#include " clang/AST/Type.h"
2121#include " clang/Basic/SourceLocation.h"
22+ #include " clang/Basic/Specifiers.h"
2223#include " clang/Sema/Lookup.h"
2324#include " clang/Sema/Sema.h"
2425#include " clang/Sema/SemaHLSL.h"
@@ -110,8 +111,11 @@ struct BuiltinTypeMethodBuilder {
110111 CXXMethodDecl *Method;
111112 bool IsConst;
112113 bool IsCtor;
114+ AccessSpecifier Access;
115+ StorageClass SC;
113116 llvm::SmallVector<Param> Params;
114117 llvm::SmallVector<Stmt *> StmtsList;
118+ llvm::SmallVector<VarDecl *> LocalVars;
115119
116120 // Argument placeholders, inspired by std::placeholder. These are the indices
117121 // of arguments to forward to `callBuiltin` and other method builder methods.
@@ -120,7 +124,16 @@ struct BuiltinTypeMethodBuilder {
120124 // LastStmt - refers to the last statement in the method body; referencing
121125 // LastStmt will remove the statement from the method body since
122126 // it will be linked from the new expression being constructed.
123- enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128 , LastStmt };
127+ enum class PlaceHolder {
128+ _0,
129+ _1,
130+ _2,
131+ _3,
132+ _4,
133+ LocalVar_0 = 64 ,
134+ Handle = 128 ,
135+ LastStmt
136+ };
124137
125138 Expr *convertPlaceholder (PlaceHolder PH);
126139 Expr *convertPlaceholder (Expr *E) { return E; }
@@ -130,13 +143,17 @@ struct BuiltinTypeMethodBuilder {
130143
131144 BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
132145 QualType ReturnTy, bool IsConst = false ,
133- bool IsCtor = false )
146+ bool IsCtor = false ,
147+ AccessSpecifier Access = AS_public,
148+ StorageClass SC = SC_None)
134149 : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr ),
135- IsConst (IsConst), IsCtor(IsCtor) {}
150+ IsConst (IsConst), IsCtor(IsCtor), Access(Access), SC(SC) {}
136151
137152 BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef NameStr,
138153 QualType ReturnTy, bool IsConst = false ,
139- bool IsCtor = false );
154+ bool IsCtor = false ,
155+ AccessSpecifier Access = AS_public,
156+ StorageClass SC = SC_None);
140157 BuiltinTypeMethodBuilder (const BuiltinTypeMethodBuilder &Other) = delete;
141158
142159 ~BuiltinTypeMethodBuilder () { finalize (); }
@@ -147,13 +164,15 @@ struct BuiltinTypeMethodBuilder {
147164 BuiltinTypeMethodBuilder &addParam (StringRef Name, QualType Ty,
148165 HLSLParamModifierAttr::Spelling Modifier =
149166 HLSLParamModifierAttr::Keyword_in);
167+ BuiltinTypeMethodBuilder &createLocalVar (StringRef Name, QualType Ty);
150168 template <typename ... Ts>
151169 BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName,
152170 QualType ReturnType, Ts... ArgSpecs);
171+ template <typename T> BuiltinTypeMethodBuilder &callHandleCtor (T HandleExpr);
153172 template <typename TLHS, typename TRHS>
154173 BuiltinTypeMethodBuilder &assign (TLHS LHS, TRHS RHS);
155174 template <typename T> BuiltinTypeMethodBuilder &dereference (T Ptr);
156- BuiltinTypeDeclBuilder &finalize ();
175+ BuiltinTypeDeclBuilder &finalize (CXXMethodDecl **OutMethod = nullptr );
157176 Expr *getResourceHandleExpr ();
158177
159178private:
@@ -328,19 +347,29 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
328347 }
329348
330349 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
350+ if (PH >= PlaceHolder::LocalVar_0) {
351+ unsigned Index = static_cast <unsigned >(PH) -
352+ static_cast <unsigned >(PlaceHolder::LocalVar_0);
353+ assert (Index < LocalVars.size () && " local var index out of range" );
354+ VarDecl *VD = LocalVars[Index];
355+ return DeclRefExpr::Create (
356+ AST, NestedNameSpecifierLoc (), SourceLocation (), VD, false ,
357+ DeclarationNameInfo (VD->getDeclName (), SourceLocation ()), VD->getType (),
358+ VK_LValue);
359+ }
360+
331361 ParmVarDecl *ParamDecl = Method->getParamDecl (static_cast <unsigned >(PH));
332362 return DeclRefExpr::Create (
333363 AST, NestedNameSpecifierLoc (), SourceLocation (), ParamDecl, false ,
334364 DeclarationNameInfo (ParamDecl->getDeclName (), SourceLocation ()),
335365 ParamDecl->getType (), VK_PRValue);
336366}
337367
338- BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB,
339- StringRef NameStr,
340- QualType ReturnTy,
341- bool IsConst, bool IsCtor)
368+ BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder (
369+ BuiltinTypeDeclBuilder &DB, StringRef NameStr, QualType ReturnTy,
370+ bool IsConst, bool IsCtor, AccessSpecifier Access, StorageClass SC)
342371 : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst),
343- IsCtor (IsCtor) {
372+ IsCtor (IsCtor), Access(Access), SC(SC) {
344373
345374 assert ((!NameStr.empty () || IsCtor) && " method needs a name" );
346375 assert (((IsCtor && !IsConst) || !IsCtor) && " constructor cannot be const" );
@@ -390,10 +419,9 @@ void BuiltinTypeMethodBuilder::createDecl() {
390419 ExplicitSpecifier (), false , true , false ,
391420 ConstexprSpecKind::Unspecified);
392421 else
393- Method =
394- CXXMethodDecl::Create (AST, DeclBuilder.Record , SourceLocation (),
395- NameInfo, FuncTy, TSInfo, SC_None, false , false ,
396- ConstexprSpecKind::Unspecified, SourceLocation ());
422+ Method = CXXMethodDecl::Create (
423+ AST, DeclBuilder.Record , SourceLocation (), NameInfo, FuncTy, TSInfo, SC,
424+ false , false , ConstexprSpecKind::Unspecified, SourceLocation ());
397425
398426 // create params & set them to the function prototype
399427 SmallVector<ParmVarDecl *> ParmDecls;
@@ -431,15 +459,31 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
431459 OK_Ordinary);
432460}
433461
462+ BuiltinTypeMethodBuilder &
463+ BuiltinTypeMethodBuilder::createLocalVar (StringRef Name, QualType Ty) {
464+ ensureCompleteDecl ();
465+
466+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
467+ VarDecl *VD =
468+ VarDecl::Create (AST, Method, SourceLocation (), SourceLocation (),
469+ &AST.Idents .get (Name, tok::TokenKind::identifier), Ty,
470+ AST.getTrivialTypeSourceInfo (Ty), SC_None);
471+ LocalVars.push_back (VD);
472+ DeclStmt *DS = new (AST)
473+ clang::DeclStmt (DeclGroupRef (VD), SourceLocation (), SourceLocation ());
474+ StmtsList.push_back (DS);
475+ return *this ;
476+ }
477+
434478template <typename ... Ts>
435479BuiltinTypeMethodBuilder &
436480BuiltinTypeMethodBuilder::callBuiltin (StringRef BuiltinName,
437481 QualType ReturnType, Ts... ArgSpecs) {
482+ ensureCompleteDecl ();
483+
438484 std::array<Expr *, sizeof ...(ArgSpecs)> Args{
439485 convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
440486
441- ensureCompleteDecl ();
442-
443487 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
444488 FunctionDecl *FD = lookupBuiltinFunction (DeclBuilder.SemaRef , BuiltinName);
445489 DeclRefExpr *DRE = DeclRefExpr::Create (
@@ -459,6 +503,25 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
459503 return *this ;
460504}
461505
506+ template <typename T>
507+ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::callHandleCtor (T Handle) {
508+ ensureCompleteDecl ();
509+
510+ Expr *HandleExpr = convertPlaceholder (Handle);
511+
512+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
513+ QualType RecordType = AST.getTypeDeclType (cast<TypeDecl>(DeclBuilder.Record ));
514+ CXXConstructorDecl *Ctor = DeclBuilder.HandleCtor ;
515+ assert (Ctor && " Handle constructor not created" );
516+
517+ CXXConstructExpr *CtorExpr = CXXConstructExpr::Create (
518+ AST, RecordType, SourceLocation (), Ctor, false , {HandleExpr}, false ,
519+ false , false , false , CXXConstructionKind::Complete, SourceRange ());
520+
521+ StmtsList.push_back (CtorExpr);
522+ return *this ;
523+ }
524+
462525template <typename TLHS, typename TRHS>
463526BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::assign (TLHS LHS, TRHS RHS) {
464527 Expr *LHSExpr = convertPlaceholder (LHS);
@@ -483,7 +546,7 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
483546 return *this ;
484547}
485548
486- BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize () {
549+ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize (CXXMethodDecl **OutMethod ) {
487550 assert (!DeclBuilder.Record ->isCompleteDefinition () &&
488551 " record is already complete" );
489552
@@ -510,11 +573,13 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
510573 Method->setBody (CompoundStmt::Create (AST, StmtsList, FPOptionsOverride (),
511574 SourceLocation (), SourceLocation ()));
512575 Method->setLexicalDeclContext (DeclBuilder.Record );
513- Method->setAccess (AccessSpecifier::AS_public );
576+ Method->setAccess (Access );
514577 Method->addAttr (AlwaysInlineAttr::CreateImplicit (
515578 AST, SourceRange (), AlwaysInlineAttr::CXX11_clang_always_inline));
516579 DeclBuilder.Record ->addDecl (Method);
517580 }
581+ if (OutMethod)
582+ *OutMethod = Method;
518583 return DeclBuilder;
519584}
520585
@@ -619,7 +684,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
619684
620685// Adds default constructor to the resource class:
621686// Resource::Resource()
622- BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor () {
687+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor () {
623688 if (Record->isCompleteDefinition ())
624689 return *this ;
625690
@@ -633,6 +698,23 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
633698 .finalize ();
634699}
635700
701+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleConstructor () {
702+ if (Record->isCompleteDefinition ())
703+ return *this ;
704+
705+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
706+ ASTContext &AST = SemaRef.getASTContext ();
707+ QualType HandleType = getResourceHandleField ()->getType ();
708+ CXXMethodDecl *OutMethod = nullptr ;
709+
710+ BuiltinTypeMethodBuilder (*this , " " , AST.VoidTy , false , true , AS_public)
711+ .addParam (" handle" , HandleType)
712+ .assign (PH::Handle, PH::_0)
713+ .finalize (&OutMethod);
714+ HandleCtor = cast<CXXConstructorDecl>(OutMethod);
715+ return *this ;
716+ }
717+
636718BuiltinTypeDeclBuilder &
637719BuiltinTypeDeclBuilder::addHandleConstructorFromBinding () {
638720 if (Record->isCompleteDefinition ())
@@ -676,6 +758,54 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
676758 .finalize ();
677759}
678760
761+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding () {
762+ if (Record->isCompleteDefinition ())
763+ return *this ;
764+
765+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
766+ ASTContext &AST = SemaRef.getASTContext ();
767+ QualType HandleType = getResourceHandleField ()->getType ();
768+ QualType RecordType = AST.getTypeDeclType (cast<TypeDecl>(Record));
769+
770+ return BuiltinTypeMethodBuilder (*this , " __createFromBinding" , RecordType,
771+ false , false , AS_public, SC_Static)
772+ .addParam (" registerNo" , AST.UnsignedIntTy )
773+ .addParam (" spaceNo" , AST.UnsignedIntTy )
774+ .addParam (" range" , AST.IntTy )
775+ .addParam (" index" , AST.UnsignedIntTy )
776+ .addParam (" name" , AST.getPointerType (AST.CharTy .withConst ()))
777+ .createLocalVar (" tmp" , HandleType)
778+ .callBuiltin (" __builtin_hlsl_resource_handlefrombinding" , HandleType,
779+ PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
780+ .callHandleCtor (PH::LastStmt)
781+ .finalize ();
782+ }
783+
784+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding () {
785+ if (Record->isCompleteDefinition ())
786+ return *this ;
787+
788+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
789+ ASTContext &AST = SemaRef.getASTContext ();
790+ QualType HandleType = getResourceHandleField ()->getType ();
791+ QualType RecordType = AST.getTypeDeclType (cast<TypeDecl>(Record));
792+
793+ return BuiltinTypeMethodBuilder (*this , " __createFromImplicitBinding" ,
794+ RecordType, false , false , AS_public,
795+ SC_Static)
796+ .addParam (" orderId" , AST.UnsignedIntTy )
797+ .addParam (" spaceNo" , AST.UnsignedIntTy )
798+ .addParam (" range" , AST.IntTy )
799+ .addParam (" index" , AST.UnsignedIntTy )
800+ .addParam (" name" , AST.getPointerType (AST.CharTy .withConst ()))
801+ .createLocalVar (" tmp" , HandleType)
802+ .callBuiltin (" __builtin_hlsl_resource_handlefromimplicitbinding" ,
803+ HandleType, PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3,
804+ PH::_4)
805+ .callHandleCtor (PH::LastStmt)
806+ .finalize ();
807+ }
808+
679809BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators () {
680810 ASTContext &AST = Record->getASTContext ();
681811 DeclarationName Subscript =
0 commit comments