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,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
483546 return *this ;
484547}
485548
486- BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize () {
549+ BuiltinTypeDeclBuilder &
550+ BuiltinTypeMethodBuilder::finalize (CXXMethodDecl **OutMethod) {
487551 assert (!DeclBuilder.Record ->isCompleteDefinition () &&
488552 " record is already complete" );
489553
@@ -510,11 +574,13 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
510574 Method->setBody (CompoundStmt::Create (AST, StmtsList, FPOptionsOverride (),
511575 SourceLocation (), SourceLocation ()));
512576 Method->setLexicalDeclContext (DeclBuilder.Record );
513- Method->setAccess (AccessSpecifier::AS_public );
577+ Method->setAccess (Access );
514578 Method->addAttr (AlwaysInlineAttr::CreateImplicit (
515579 AST, SourceRange (), AlwaysInlineAttr::CXX11_clang_always_inline));
516580 DeclBuilder.Record ->addDecl (Method);
517581 }
582+ if (OutMethod)
583+ *OutMethod = Method;
518584 return DeclBuilder;
519585}
520586
@@ -619,7 +685,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
619685
620686// Adds default constructor to the resource class:
621687// Resource::Resource()
622- BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor () {
688+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor () {
623689 if (Record->isCompleteDefinition ())
624690 return *this ;
625691
@@ -633,6 +699,23 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
633699 .finalize ();
634700}
635701
702+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleConstructor () {
703+ if (Record->isCompleteDefinition ())
704+ return *this ;
705+
706+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
707+ ASTContext &AST = SemaRef.getASTContext ();
708+ QualType HandleType = getResourceHandleField ()->getType ();
709+ CXXMethodDecl *OutMethod = nullptr ;
710+
711+ BuiltinTypeMethodBuilder (*this , " " , AST.VoidTy , false , true , AS_public)
712+ .addParam (" handle" , HandleType)
713+ .assign (PH::Handle, PH::_0)
714+ .finalize (&OutMethod);
715+ HandleCtor = cast<CXXConstructorDecl>(OutMethod);
716+ return *this ;
717+ }
718+
636719BuiltinTypeDeclBuilder &
637720BuiltinTypeDeclBuilder::addHandleConstructorFromBinding () {
638721 if (Record->isCompleteDefinition ())
@@ -676,6 +759,54 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
676759 .finalize ();
677760}
678761
762+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding () {
763+ if (Record->isCompleteDefinition ())
764+ return *this ;
765+
766+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
767+ ASTContext &AST = SemaRef.getASTContext ();
768+ QualType HandleType = getResourceHandleField ()->getType ();
769+ QualType RecordType = AST.getTypeDeclType (cast<TypeDecl>(Record));
770+
771+ return BuiltinTypeMethodBuilder (*this , " __createFromBinding" , RecordType,
772+ false , false , AS_public, SC_Static)
773+ .addParam (" registerNo" , AST.UnsignedIntTy )
774+ .addParam (" spaceNo" , AST.UnsignedIntTy )
775+ .addParam (" range" , AST.IntTy )
776+ .addParam (" index" , AST.UnsignedIntTy )
777+ .addParam (" name" , AST.getPointerType (AST.CharTy .withConst ()))
778+ .createLocalVar (" tmp" , HandleType)
779+ .callBuiltin (" __builtin_hlsl_resource_handlefrombinding" , HandleType,
780+ PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
781+ .callHandleCtor (PH::LastStmt)
782+ .finalize ();
783+ }
784+
785+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding () {
786+ if (Record->isCompleteDefinition ())
787+ return *this ;
788+
789+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
790+ ASTContext &AST = SemaRef.getASTContext ();
791+ QualType HandleType = getResourceHandleField ()->getType ();
792+ QualType RecordType = AST.getTypeDeclType (cast<TypeDecl>(Record));
793+
794+ return BuiltinTypeMethodBuilder (*this , " __createFromImplicitBinding" ,
795+ RecordType, false , false , AS_public,
796+ SC_Static)
797+ .addParam (" orderId" , AST.UnsignedIntTy )
798+ .addParam (" spaceNo" , AST.UnsignedIntTy )
799+ .addParam (" range" , AST.IntTy )
800+ .addParam (" index" , AST.UnsignedIntTy )
801+ .addParam (" name" , AST.getPointerType (AST.CharTy .withConst ()))
802+ .createLocalVar (" tmp" , HandleType)
803+ .callBuiltin (" __builtin_hlsl_resource_handlefromimplicitbinding" ,
804+ HandleType, PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3,
805+ PH::_4)
806+ .callHandleCtor (PH::LastStmt)
807+ .finalize ();
808+ }
809+
679810BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators () {
680811 ASTContext &AST = Record->getASTContext ();
681812 DeclarationName Subscript =
0 commit comments