19
19
#include " clang/AST/Expr.h"
20
20
#include " clang/AST/Type.h"
21
21
#include " clang/Basic/SourceLocation.h"
22
+ #include " clang/Basic/Specifiers.h"
22
23
#include " clang/Sema/Lookup.h"
23
24
#include " clang/Sema/Sema.h"
24
25
#include " clang/Sema/SemaHLSL.h"
@@ -102,6 +103,13 @@ struct BuiltinTypeMethodBuilder {
102
103
: NameII(NameII), Ty(Ty), Modifier(Modifier) {}
103
104
};
104
105
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
+
105
113
BuiltinTypeDeclBuilder &DeclBuilder;
106
114
DeclarationName Name;
107
115
QualType ReturnTy;
@@ -110,6 +118,7 @@ struct BuiltinTypeMethodBuilder {
110
118
CXXMethodDecl *Method;
111
119
bool IsConst;
112
120
bool IsCtor;
121
+ StorageClass SC;
113
122
llvm::SmallVector<Param> Params;
114
123
llvm::SmallVector<Stmt *> StmtsList;
115
124
@@ -123,20 +132,21 @@ struct BuiltinTypeMethodBuilder {
123
132
enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128 , LastStmt };
124
133
125
134
Expr *convertPlaceholder (PlaceHolder PH);
135
+ Expr *convertPlaceholder (LocalVar &Var);
126
136
Expr *convertPlaceholder (Expr *E) { return E; }
127
137
128
138
public:
129
139
friend BuiltinTypeDeclBuilder;
130
140
131
141
BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
132
142
QualType ReturnTy, bool IsConst = false ,
133
- bool IsCtor = false )
143
+ bool IsCtor = false , StorageClass SC = SC_None )
134
144
: DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr ),
135
- IsConst (IsConst), IsCtor(IsCtor) {}
145
+ IsConst (IsConst), IsCtor(IsCtor), SC(SC) {}
136
146
137
147
BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef NameStr,
138
148
QualType ReturnTy, bool IsConst = false ,
139
- bool IsCtor = false );
149
+ bool IsCtor = false , StorageClass SC = SC_None );
140
150
BuiltinTypeMethodBuilder (const BuiltinTypeMethodBuilder &Other) = delete;
141
151
142
152
~BuiltinTypeMethodBuilder () { finalize (); }
@@ -147,18 +157,22 @@ struct BuiltinTypeMethodBuilder {
147
157
BuiltinTypeMethodBuilder &addParam (StringRef Name, QualType Ty,
148
158
HLSLParamModifierAttr::Spelling Modifier =
149
159
HLSLParamModifierAttr::Keyword_in);
160
+ BuiltinTypeMethodBuilder &declareLocalVar (LocalVar &Var);
150
161
template <typename ... Ts>
151
162
BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName,
152
163
QualType ReturnType, Ts... ArgSpecs);
153
164
template <typename TLHS, typename TRHS>
154
165
BuiltinTypeMethodBuilder &assign (TLHS LHS, TRHS RHS);
155
166
template <typename T> BuiltinTypeMethodBuilder &dereference (T Ptr);
156
- BuiltinTypeDeclBuilder &finalize ();
157
- Expr *getResourceHandleExpr ();
158
-
159
167
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);
161
173
BuiltinTypeMethodBuilder &returnThis ();
174
+ BuiltinTypeDeclBuilder &finalize ();
175
+ Expr *getResourceHandleExpr ();
162
176
163
177
private:
164
178
void createDecl ();
@@ -339,12 +353,22 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
339
353
ParamDecl->getType ().getNonReferenceType (), VK_PRValue);
340
354
}
341
355
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
+
342
365
BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB,
343
366
StringRef NameStr,
344
367
QualType ReturnTy,
345
- bool IsConst, bool IsCtor)
368
+ bool IsConst, bool IsCtor,
369
+ StorageClass SC)
346
370
: DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst),
347
- IsCtor (IsCtor) {
371
+ IsCtor (IsCtor), SC(SC) {
348
372
349
373
assert ((!NameStr.empty () || IsCtor) && " method needs a name" );
350
374
assert (((IsCtor && !IsConst) || !IsCtor) && " constructor cannot be const" );
@@ -394,10 +418,9 @@ void BuiltinTypeMethodBuilder::createDecl() {
394
418
ExplicitSpecifier (), false , true , false ,
395
419
ConstexprSpecKind::Unspecified);
396
420
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 ());
401
424
402
425
// create params & set them to the function prototype
403
426
SmallVector<ParmVarDecl *> ParmDecls;
@@ -435,19 +458,20 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
435
458
OK_Ordinary);
436
459
}
437
460
438
- template <typename T>
439
461
BuiltinTypeMethodBuilder &
440
- BuiltinTypeMethodBuilder::getResourceHandle (T ResourceRecord ) {
462
+ BuiltinTypeMethodBuilder::declareLocalVar (LocalVar &Var ) {
441
463
ensureCompleteDecl ();
442
464
443
- Expr *ResourceExpr = convertPlaceholder (ResourceRecord );
465
+ assert (Var. Decl == nullptr && " local variable is already declared " );
444
466
445
467
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);
451
475
return *this ;
452
476
}
453
477
@@ -464,11 +488,11 @@ template <typename... Ts>
464
488
BuiltinTypeMethodBuilder &
465
489
BuiltinTypeMethodBuilder::callBuiltin (StringRef BuiltinName,
466
490
QualType ReturnType, Ts... ArgSpecs) {
491
+ ensureCompleteDecl ();
492
+
467
493
std::array<Expr *, sizeof ...(ArgSpecs)> Args{
468
494
convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
469
495
470
- ensureCompleteDecl ();
471
-
472
496
ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
473
497
FunctionDecl *FD = lookupBuiltinFunction (DeclBuilder.SemaRef , BuiltinName);
474
498
DeclRefExpr *DRE = DeclRefExpr::Create (
@@ -512,6 +536,55 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
512
536
return *this ;
513
537
}
514
538
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
+
515
588
BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize () {
516
589
assert (!DeclBuilder.Record ->isCompleteDefinition () &&
517
590
" record is already complete" );
@@ -539,7 +612,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
539
612
Method->setBody (CompoundStmt::Create (AST, StmtsList, FPOptionsOverride (),
540
613
SourceLocation (), SourceLocation ()));
541
614
Method->setLexicalDeclContext (DeclBuilder.Record );
542
- Method->setAccess (AccessSpecifier:: AS_public);
615
+ Method->setAccess (AS_public);
543
616
Method->addAttr (AlwaysInlineAttr::CreateImplicit (
544
617
AST, SourceRange (), AlwaysInlineAttr::CXX11_clang_always_inline));
545
618
DeclBuilder.Record ->addDecl (Method);
@@ -705,6 +778,82 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
705
778
.finalize ();
706
779
}
707
780
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
+
708
857
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor () {
709
858
if (Record->isCompleteDefinition ())
710
859
return *this ;
@@ -719,7 +868,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() {
719
868
return BuiltinTypeMethodBuilder (*this , /* Name=*/ " " , AST.VoidTy ,
720
869
/* IsConst=*/ false , /* IsCtor=*/ true )
721
870
.addParam (" other" , ConstRecordRefType)
722
- .getResourceHandle (PH::_0)
871
+ .accessHandleFieldOnResource (PH::_0)
723
872
.assign (PH::Handle, PH::LastStmt)
724
873
.finalize ();
725
874
}
@@ -738,7 +887,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
738
887
DeclarationName Name = AST.DeclarationNames .getCXXOperatorName (OO_Equal);
739
888
return BuiltinTypeMethodBuilder (*this , Name, RecordRefType)
740
889
.addParam (" other" , ConstRecordRefType)
741
- .getResourceHandle (PH::_0)
890
+ .accessHandleFieldOnResource (PH::_0)
742
891
.assign (PH::Handle, PH::LastStmt)
743
892
.returnThis ()
744
893
.finalize ();
0 commit comments