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"
@@ -102,6 +103,13 @@ struct BuiltinTypeMethodBuilder {
102103 : NameII(NameII), Ty(Ty), Modifier(Modifier) {}
103104 };
104105
106+ struct LocalVar {
107+ StringRef Name;
108+ QualType Ty;
109+ VarDecl *Decl;
110+ LocalVar (StringRef Name, QualType Ty) : Name(Name), Ty(Ty), Decl(nullptr ) {}
111+ };
112+
105113 BuiltinTypeDeclBuilder &DeclBuilder;
106114 DeclarationName Name;
107115 QualType ReturnTy;
@@ -110,6 +118,7 @@ struct BuiltinTypeMethodBuilder {
110118 CXXMethodDecl *Method;
111119 bool IsConst;
112120 bool IsCtor;
121+ StorageClass SC;
113122 llvm::SmallVector<Param> Params;
114123 llvm::SmallVector<Stmt *> StmtsList;
115124
@@ -123,20 +132,21 @@ struct BuiltinTypeMethodBuilder {
123132 enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128 , LastStmt };
124133
125134 Expr *convertPlaceholder (PlaceHolder PH);
135+ Expr *convertPlaceholder (LocalVar &Var);
126136 Expr *convertPlaceholder (Expr *E) { return E; }
127137
128138public:
129139 friend BuiltinTypeDeclBuilder;
130140
131141 BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
132142 QualType ReturnTy, bool IsConst = false ,
133- bool IsCtor = false )
143+ bool IsCtor = false , StorageClass SC = SC_None )
134144 : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr ),
135- IsConst (IsConst), IsCtor(IsCtor) {}
145+ IsConst (IsConst), IsCtor(IsCtor), SC(SC) {}
136146
137147 BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef NameStr,
138148 QualType ReturnTy, bool IsConst = false ,
139- bool IsCtor = false );
149+ bool IsCtor = false , StorageClass SC = SC_None );
140150 BuiltinTypeMethodBuilder (const BuiltinTypeMethodBuilder &Other) = delete;
141151
142152 ~BuiltinTypeMethodBuilder () { finalize (); }
@@ -147,18 +157,22 @@ struct BuiltinTypeMethodBuilder {
147157 BuiltinTypeMethodBuilder &addParam (StringRef Name, QualType Ty,
148158 HLSLParamModifierAttr::Spelling Modifier =
149159 HLSLParamModifierAttr::Keyword_in);
160+ BuiltinTypeMethodBuilder &declareLocalVar (LocalVar &Var);
150161 template <typename ... Ts>
151162 BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName,
152163 QualType ReturnType, Ts... ArgSpecs);
153164 template <typename TLHS, typename TRHS>
154165 BuiltinTypeMethodBuilder &assign (TLHS LHS, TRHS RHS);
155166 template <typename T> BuiltinTypeMethodBuilder &dereference (T Ptr);
156- BuiltinTypeDeclBuilder &finalize ();
157- Expr *getResourceHandleExpr ();
158-
159167 template <typename T>
160- BuiltinTypeMethodBuilder &getResourceHandle (T ResourceRecord);
168+ BuiltinTypeMethodBuilder &accessHandleFieldOnResource (T ResourceRecord);
169+ template <typename ResourceT, typename ValueT>
170+ BuiltinTypeMethodBuilder &setHandleFieldOnResource (ResourceT ResourceRecord,
171+ ValueT HandleValue);
172+ template <typename T> BuiltinTypeMethodBuilder &returnValue (T ReturnValue);
161173 BuiltinTypeMethodBuilder &returnThis ();
174+ BuiltinTypeDeclBuilder &finalize ();
175+ Expr *getResourceHandleExpr ();
162176
163177private:
164178 void createDecl ();
@@ -339,12 +353,22 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
339353 ParamDecl->getType ().getNonReferenceType (), VK_PRValue);
340354}
341355
356+ Expr *BuiltinTypeMethodBuilder::convertPlaceholder (LocalVar &Var) {
357+ VarDecl *VD = Var.Decl ;
358+ assert (VD && " local variable is not declared" );
359+ return DeclRefExpr::Create (
360+ VD->getASTContext (), NestedNameSpecifierLoc (), SourceLocation (), VD,
361+ false , DeclarationNameInfo (VD->getDeclName (), SourceLocation ()),
362+ VD->getType (), VK_LValue);
363+ }
364+
342365BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB,
343366 StringRef NameStr,
344367 QualType ReturnTy,
345- bool IsConst, bool IsCtor)
368+ bool IsConst, bool IsCtor,
369+ StorageClass SC)
346370 : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst),
347- IsCtor (IsCtor) {
371+ IsCtor (IsCtor), SC(SC) {
348372
349373 assert ((!NameStr.empty () || IsCtor) && " method needs a name" );
350374 assert (((IsCtor && !IsConst) || !IsCtor) && " constructor cannot be const" );
@@ -394,10 +418,9 @@ void BuiltinTypeMethodBuilder::createDecl() {
394418 ExplicitSpecifier (), false , true , false ,
395419 ConstexprSpecKind::Unspecified);
396420 else
397- Method =
398- CXXMethodDecl::Create (AST, DeclBuilder.Record , SourceLocation (),
399- NameInfo, FuncTy, TSInfo, SC_None, false , false ,
400- ConstexprSpecKind::Unspecified, SourceLocation ());
421+ Method = CXXMethodDecl::Create (
422+ AST, DeclBuilder.Record , SourceLocation (), NameInfo, FuncTy, TSInfo, SC,
423+ false , false , ConstexprSpecKind::Unspecified, SourceLocation ());
401424
402425 // create params & set them to the function prototype
403426 SmallVector<ParmVarDecl *> ParmDecls;
@@ -435,19 +458,20 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
435458 OK_Ordinary);
436459}
437460
438- template <typename T>
439461BuiltinTypeMethodBuilder &
440- BuiltinTypeMethodBuilder::getResourceHandle (T ResourceRecord ) {
462+ BuiltinTypeMethodBuilder::declareLocalVar (LocalVar &Var ) {
441463 ensureCompleteDecl ();
442464
443- Expr *ResourceExpr = convertPlaceholder (ResourceRecord );
465+ assert (Var. Decl == nullptr && " local variable is already declared " );
444466
445467 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
446- FieldDecl *HandleField = DeclBuilder.getResourceHandleField ();
447- MemberExpr *HandleExpr = MemberExpr::CreateImplicit (
448- AST, ResourceExpr, /* IsArrow=*/ false , HandleField, HandleField->getType (),
449- VK_LValue, OK_Ordinary);
450- StmtsList.push_back (HandleExpr);
468+ Var.Decl = VarDecl::Create (
469+ AST, Method, SourceLocation (), SourceLocation (),
470+ &AST.Idents .get (Var.Name , tok::TokenKind::identifier), Var.Ty ,
471+ AST.getTrivialTypeSourceInfo (Var.Ty , SourceLocation ()), SC_None);
472+ DeclStmt *DS = new (AST) clang::DeclStmt (DeclGroupRef (Var.Decl ),
473+ SourceLocation (), SourceLocation ());
474+ StmtsList.push_back (DS);
451475 return *this ;
452476}
453477
@@ -464,11 +488,11 @@ template <typename... Ts>
464488BuiltinTypeMethodBuilder &
465489BuiltinTypeMethodBuilder::callBuiltin (StringRef BuiltinName,
466490 QualType ReturnType, Ts... ArgSpecs) {
491+ ensureCompleteDecl ();
492+
467493 std::array<Expr *, sizeof ...(ArgSpecs)> Args{
468494 convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
469495
470- ensureCompleteDecl ();
471-
472496 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
473497 FunctionDecl *FD = lookupBuiltinFunction (DeclBuilder.SemaRef , BuiltinName);
474498 DeclRefExpr *DRE = DeclRefExpr::Create (
@@ -512,6 +536,55 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
512536 return *this ;
513537}
514538
539+ template <typename T>
540+ BuiltinTypeMethodBuilder &
541+ BuiltinTypeMethodBuilder::accessHandleFieldOnResource (T ResourceRecord) {
542+ ensureCompleteDecl ();
543+
544+ Expr *ResourceExpr = convertPlaceholder (ResourceRecord);
545+
546+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
547+ FieldDecl *HandleField = DeclBuilder.getResourceHandleField ();
548+ MemberExpr *HandleExpr = MemberExpr::CreateImplicit (
549+ AST, ResourceExpr, false , HandleField, HandleField->getType (), VK_LValue,
550+ OK_Ordinary);
551+ StmtsList.push_back (HandleExpr);
552+ return *this ;
553+ }
554+
555+ template <typename ResourceT, typename ValueT>
556+ BuiltinTypeMethodBuilder &
557+ BuiltinTypeMethodBuilder::setHandleFieldOnResource (ResourceT ResourceRecord,
558+ ValueT HandleValue) {
559+ ensureCompleteDecl ();
560+
561+ Expr *ResourceExpr = convertPlaceholder (ResourceRecord);
562+ Expr *HandleValueExpr = convertPlaceholder (HandleValue);
563+
564+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
565+ FieldDecl *HandleField = DeclBuilder.getResourceHandleField ();
566+ MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit (
567+ AST, ResourceExpr, false , HandleField, HandleField->getType (), VK_LValue,
568+ OK_Ordinary);
569+ Stmt *AssignStmt = BinaryOperator::Create (
570+ DeclBuilder.SemaRef .getASTContext (), HandleMemberExpr, HandleValueExpr,
571+ BO_Assign, HandleMemberExpr->getType (), ExprValueKind::VK_PRValue,
572+ ExprObjectKind::OK_Ordinary, SourceLocation (), FPOptionsOverride ());
573+ StmtsList.push_back (AssignStmt);
574+ return *this ;
575+ }
576+
577+ template <typename T>
578+ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue (T ReturnValue) {
579+ ensureCompleteDecl ();
580+
581+ Expr *ReturnValueExpr = convertPlaceholder (ReturnValue);
582+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
583+ StmtsList.push_back (
584+ ReturnStmt::Create (AST, SourceLocation (), ReturnValueExpr, nullptr ));
585+ return *this ;
586+ }
587+
515588BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize () {
516589 assert (!DeclBuilder.Record ->isCompleteDefinition () &&
517590 " record is already complete" );
@@ -539,7 +612,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
539612 Method->setBody (CompoundStmt::Create (AST, StmtsList, FPOptionsOverride (),
540613 SourceLocation (), SourceLocation ()));
541614 Method->setLexicalDeclContext (DeclBuilder.Record );
542- Method->setAccess (AccessSpecifier:: AS_public);
615+ Method->setAccess (AS_public);
543616 Method->addAttr (AlwaysInlineAttr::CreateImplicit (
544617 AST, SourceRange (), AlwaysInlineAttr::CXX11_clang_always_inline));
545618 DeclBuilder.Record ->addDecl (Method);
@@ -705,6 +778,82 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
705778 .finalize ();
706779}
707780
781+ // Adds static method that initializes resource from binding:
782+ //
783+ // static Resource<T> __createFromBinding(unsigned registerNo,
784+ // unsigned spaceNo, int range,
785+ // unsigned index, const char *name) {
786+ // Resource<T> tmp;
787+ // tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
788+ // tmp.__handle, registerNo, spaceNo,
789+ // range, index, name);
790+ // return tmp;
791+ // }
792+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding () {
793+ if (Record->isCompleteDefinition ())
794+ return *this ;
795+
796+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
797+ ASTContext &AST = SemaRef.getASTContext ();
798+ QualType HandleType = getResourceHandleField ()->getType ();
799+ QualType RecordType = AST.getTypeDeclType (cast<TypeDecl>(Record));
800+ BuiltinTypeMethodBuilder::LocalVar TmpVar (" tmp" , RecordType);
801+
802+ return BuiltinTypeMethodBuilder (*this , " __createFromBinding" , RecordType,
803+ false , false , SC_Static)
804+ .addParam (" registerNo" , AST.UnsignedIntTy )
805+ .addParam (" spaceNo" , AST.UnsignedIntTy )
806+ .addParam (" range" , AST.IntTy )
807+ .addParam (" index" , AST.UnsignedIntTy )
808+ .addParam (" name" , AST.getPointerType (AST.CharTy .withConst ()))
809+ .declareLocalVar (TmpVar)
810+ .accessHandleFieldOnResource (TmpVar)
811+ .callBuiltin (" __builtin_hlsl_resource_handlefrombinding" , HandleType,
812+ PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
813+ .setHandleFieldOnResource (TmpVar, PH::LastStmt)
814+ .returnValue (TmpVar)
815+ .finalize ();
816+ }
817+
818+ // Adds static method that initializes resource from binding:
819+ //
820+ // static Resource<T> __createFromImplicitBinding(unsigned orderId,
821+ // unsigned spaceNo, int range,
822+ // unsigned index,
823+ // const char *name) {
824+ // Resource<T> tmp;
825+ // tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
826+ // tmp.__handle, spaceNo,
827+ // range, index, orderId, name);
828+ // return tmp;
829+ // }
830+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding () {
831+ if (Record->isCompleteDefinition ())
832+ return *this ;
833+
834+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
835+ ASTContext &AST = SemaRef.getASTContext ();
836+ QualType HandleType = getResourceHandleField ()->getType ();
837+ QualType RecordType = AST.getTypeDeclType (cast<TypeDecl>(Record));
838+ BuiltinTypeMethodBuilder::LocalVar TmpVar (" tmp" , RecordType);
839+
840+ return BuiltinTypeMethodBuilder (*this , " __createFromImplicitBinding" ,
841+ RecordType, false , false , SC_Static)
842+ .addParam (" orderId" , AST.UnsignedIntTy )
843+ .addParam (" spaceNo" , AST.UnsignedIntTy )
844+ .addParam (" range" , AST.IntTy )
845+ .addParam (" index" , AST.UnsignedIntTy )
846+ .addParam (" name" , AST.getPointerType (AST.CharTy .withConst ()))
847+ .declareLocalVar (TmpVar)
848+ .accessHandleFieldOnResource (TmpVar)
849+ .callBuiltin (" __builtin_hlsl_resource_handlefromimplicitbinding" ,
850+ HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
851+ PH::_4)
852+ .setHandleFieldOnResource (TmpVar, PH::LastStmt)
853+ .returnValue (TmpVar)
854+ .finalize ();
855+ }
856+
708857BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor () {
709858 if (Record->isCompleteDefinition ())
710859 return *this ;
@@ -719,7 +868,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() {
719868 return BuiltinTypeMethodBuilder (*this , /* Name=*/ " " , AST.VoidTy ,
720869 /* IsConst=*/ false , /* IsCtor=*/ true )
721870 .addParam (" other" , ConstRecordRefType)
722- .getResourceHandle (PH::_0)
871+ .accessHandleFieldOnResource (PH::_0)
723872 .assign (PH::Handle, PH::LastStmt)
724873 .finalize ();
725874}
@@ -738,7 +887,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
738887 DeclarationName Name = AST.DeclarationNames .getCXXOperatorName (OO_Equal);
739888 return BuiltinTypeMethodBuilder (*this , Name, RecordRefType)
740889 .addParam (" other" , ConstRecordRefType)
741- .getResourceHandle (PH::_0)
890+ .accessHandleFieldOnResource (PH::_0)
742891 .assign (PH::Handle, PH::LastStmt)
743892 .returnThis ()
744893 .finalize ();
0 commit comments