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"
@@ -110,8 +111,11 @@ struct BuiltinTypeMethodBuilder {
110
111
CXXMethodDecl *Method;
111
112
bool IsConst;
112
113
bool IsCtor;
114
+ AccessSpecifier Access;
115
+ StorageClass SC;
113
116
llvm::SmallVector<Param> Params;
114
117
llvm::SmallVector<Stmt *> StmtsList;
118
+ llvm::SmallVector<VarDecl *> LocalVars;
115
119
116
120
// Argument placeholders, inspired by std::placeholder. These are the indices
117
121
// of arguments to forward to `callBuiltin` and other method builder methods.
@@ -120,7 +124,16 @@ struct BuiltinTypeMethodBuilder {
120
124
// LastStmt - refers to the last statement in the method body; referencing
121
125
// LastStmt will remove the statement from the method body since
122
126
// 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
+ };
124
137
125
138
Expr *convertPlaceholder (PlaceHolder PH);
126
139
Expr *convertPlaceholder (Expr *E) { return E; }
@@ -130,13 +143,17 @@ struct BuiltinTypeMethodBuilder {
130
143
131
144
BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
132
145
QualType ReturnTy, bool IsConst = false ,
133
- bool IsCtor = false )
146
+ bool IsCtor = false ,
147
+ AccessSpecifier Access = AS_public,
148
+ StorageClass SC = SC_None)
134
149
: DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr ),
135
- IsConst (IsConst), IsCtor(IsCtor) {}
150
+ IsConst (IsConst), IsCtor(IsCtor), Access(Access), SC(SC) {}
136
151
137
152
BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef NameStr,
138
153
QualType ReturnTy, bool IsConst = false ,
139
- bool IsCtor = false );
154
+ bool IsCtor = false ,
155
+ AccessSpecifier Access = AS_public,
156
+ StorageClass SC = SC_None);
140
157
BuiltinTypeMethodBuilder (const BuiltinTypeMethodBuilder &Other) = delete;
141
158
142
159
~BuiltinTypeMethodBuilder () { finalize (); }
@@ -147,13 +164,15 @@ struct BuiltinTypeMethodBuilder {
147
164
BuiltinTypeMethodBuilder &addParam (StringRef Name, QualType Ty,
148
165
HLSLParamModifierAttr::Spelling Modifier =
149
166
HLSLParamModifierAttr::Keyword_in);
167
+ BuiltinTypeMethodBuilder &createLocalVar (StringRef Name, QualType Ty);
150
168
template <typename ... Ts>
151
169
BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName,
152
170
QualType ReturnType, Ts... ArgSpecs);
171
+ template <typename T> BuiltinTypeMethodBuilder &callHandleCtor (T HandleExpr);
153
172
template <typename TLHS, typename TRHS>
154
173
BuiltinTypeMethodBuilder &assign (TLHS LHS, TRHS RHS);
155
174
template <typename T> BuiltinTypeMethodBuilder &dereference (T Ptr);
156
- BuiltinTypeDeclBuilder &finalize ();
175
+ BuiltinTypeDeclBuilder &finalize (CXXMethodDecl **OutMethod = nullptr );
157
176
Expr *getResourceHandleExpr ();
158
177
159
178
private:
@@ -328,19 +347,29 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
328
347
}
329
348
330
349
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
+
331
361
ParmVarDecl *ParamDecl = Method->getParamDecl (static_cast <unsigned >(PH));
332
362
return DeclRefExpr::Create (
333
363
AST, NestedNameSpecifierLoc (), SourceLocation (), ParamDecl, false ,
334
364
DeclarationNameInfo (ParamDecl->getDeclName (), SourceLocation ()),
335
365
ParamDecl->getType (), VK_PRValue);
336
366
}
337
367
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)
342
371
: DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst),
343
- IsCtor (IsCtor) {
372
+ IsCtor (IsCtor), Access(Access), SC(SC) {
344
373
345
374
assert ((!NameStr.empty () || IsCtor) && " method needs a name" );
346
375
assert (((IsCtor && !IsConst) || !IsCtor) && " constructor cannot be const" );
@@ -390,10 +419,9 @@ void BuiltinTypeMethodBuilder::createDecl() {
390
419
ExplicitSpecifier (), false , true , false ,
391
420
ConstexprSpecKind::Unspecified);
392
421
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 ());
397
425
398
426
// create params & set them to the function prototype
399
427
SmallVector<ParmVarDecl *> ParmDecls;
@@ -431,15 +459,31 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
431
459
OK_Ordinary);
432
460
}
433
461
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
+
434
478
template <typename ... Ts>
435
479
BuiltinTypeMethodBuilder &
436
480
BuiltinTypeMethodBuilder::callBuiltin (StringRef BuiltinName,
437
481
QualType ReturnType, Ts... ArgSpecs) {
482
+ ensureCompleteDecl ();
483
+
438
484
std::array<Expr *, sizeof ...(ArgSpecs)> Args{
439
485
convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
440
486
441
- ensureCompleteDecl ();
442
-
443
487
ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
444
488
FunctionDecl *FD = lookupBuiltinFunction (DeclBuilder.SemaRef , BuiltinName);
445
489
DeclRefExpr *DRE = DeclRefExpr::Create (
@@ -459,6 +503,25 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
459
503
return *this ;
460
504
}
461
505
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
+
462
525
template <typename TLHS, typename TRHS>
463
526
BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::assign (TLHS LHS, TRHS RHS) {
464
527
Expr *LHSExpr = convertPlaceholder (LHS);
@@ -483,7 +546,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
483
546
return *this ;
484
547
}
485
548
486
- BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize () {
549
+ BuiltinTypeDeclBuilder &
550
+ BuiltinTypeMethodBuilder::finalize (CXXMethodDecl **OutMethod) {
487
551
assert (!DeclBuilder.Record ->isCompleteDefinition () &&
488
552
" record is already complete" );
489
553
@@ -510,11 +574,13 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
510
574
Method->setBody (CompoundStmt::Create (AST, StmtsList, FPOptionsOverride (),
511
575
SourceLocation (), SourceLocation ()));
512
576
Method->setLexicalDeclContext (DeclBuilder.Record );
513
- Method->setAccess (AccessSpecifier::AS_public );
577
+ Method->setAccess (Access );
514
578
Method->addAttr (AlwaysInlineAttr::CreateImplicit (
515
579
AST, SourceRange (), AlwaysInlineAttr::CXX11_clang_always_inline));
516
580
DeclBuilder.Record ->addDecl (Method);
517
581
}
582
+ if (OutMethod)
583
+ *OutMethod = Method;
518
584
return DeclBuilder;
519
585
}
520
586
@@ -619,7 +685,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
619
685
620
686
// Adds default constructor to the resource class:
621
687
// Resource::Resource()
622
- BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor () {
688
+ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor () {
623
689
if (Record->isCompleteDefinition ())
624
690
return *this ;
625
691
@@ -633,6 +699,23 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
633
699
.finalize ();
634
700
}
635
701
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
+
636
719
BuiltinTypeDeclBuilder &
637
720
BuiltinTypeDeclBuilder::addHandleConstructorFromBinding () {
638
721
if (Record->isCompleteDefinition ())
@@ -676,6 +759,54 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
676
759
.finalize ();
677
760
}
678
761
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
+
679
810
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators () {
680
811
ASTContext &AST = Record->getASTContext ();
681
812
DeclarationName Subscript =
0 commit comments