@@ -67,45 +67,50 @@ struct TemplateParameterListBuilder {
67
67
BuiltinTypeDeclBuilder &finalizeTemplateArgs (ConceptDecl *CD = nullptr );
68
68
};
69
69
70
- // Builder for methods of builtin types. Allows adding methods to builtin types
71
- // using the builder pattern like this:
70
+ // Builder for methods or constructors of builtin types. Allows creating methods
71
+ // or constructors of builtin types using the builder pattern like this:
72
72
//
73
73
// BuiltinTypeMethodBuilder(RecordBuilder, "MethodName", ReturnType)
74
74
// .addParam("param_name", Type, InOutModifier)
75
75
// .callBuiltin("builtin_name", BuiltinParams...)
76
- // .finalizeMethod ();
76
+ // .finalize ();
77
77
//
78
- // The builder needs to have all of the method parameters before it can create
79
- // a CXXMethodDecl. It collects them in addParam calls and when a first
80
- // method that builds the body is called or when access to 'this` is needed it
81
- // creates the CXXMethodDecl and ParmVarDecls instances. These can then be
82
- // referenced from the body building methods. Destructor or an explicit call to
83
- // finalizeMethod() will complete the method definition.
78
+ // The builder needs to have all of the parameters before it can create
79
+ // a CXXMethodDecl or CXXConstructorDecl. It collects them in addParam calls and
80
+ // when a first method that builds the body is called or when access to 'this`
81
+ // is needed it creates the CXXMethodDecl/CXXConstructorDecl and ParmVarDecls
82
+ // instances. These can then be referenced from the body building methods.
83
+ // Destructor or an explicit call to finalize() will complete the method
84
+ // definition.
84
85
//
85
86
// The callBuiltin helper method accepts constants via `Expr *` or placeholder
86
87
// value arguments to indicate which function arguments to forward to the
87
88
// builtin.
88
89
//
89
90
// If the method that is being built has a non-void return type the
90
- // finalizeMethod will create a return statent with the value of the last
91
- // statement (unless the last statement is already a ReturnStmt).
91
+ // finalize() will create a return statement with the value of the last
92
+ // statement (unless the last statement is already a ReturnStmt or the return
93
+ // value is void).
92
94
struct BuiltinTypeMethodBuilder {
93
95
private:
94
- struct MethodParam {
96
+ struct Param {
95
97
const IdentifierInfo &NameII;
96
98
QualType Ty;
97
99
HLSLParamModifierAttr::Spelling Modifier;
98
- MethodParam (const IdentifierInfo &NameII, QualType Ty,
99
- HLSLParamModifierAttr::Spelling Modifier)
100
+ Param (const IdentifierInfo &NameII, QualType Ty,
101
+ HLSLParamModifierAttr::Spelling Modifier)
100
102
: NameII(NameII), Ty(Ty), Modifier(Modifier) {}
101
103
};
102
104
103
105
BuiltinTypeDeclBuilder &DeclBuilder;
104
- DeclarationNameInfo NameInfo ;
106
+ DeclarationName Name ;
105
107
QualType ReturnTy;
108
+ // method or constructor declaration
109
+ // (CXXConstructorDecl derives from CXXMethodDecl)
106
110
CXXMethodDecl *Method;
107
111
bool IsConst;
108
- llvm::SmallVector<MethodParam> Params;
112
+ bool IsCtor;
113
+ llvm::SmallVector<Param> Params;
109
114
llvm::SmallVector<Stmt *> StmtsList;
110
115
111
116
// Argument placeholders, inspired by std::placeholder. These are the indices
@@ -124,15 +129,17 @@ struct BuiltinTypeMethodBuilder {
124
129
friend BuiltinTypeDeclBuilder;
125
130
126
131
BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
127
- QualType ReturnTy, bool IsConst = false )
128
- : DeclBuilder(DB), NameInfo(DeclarationNameInfo(Name, SourceLocation())),
129
- ReturnTy (ReturnTy), Method(nullptr ), IsConst(IsConst) {}
130
-
131
- BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef Name,
132
- QualType ReturnTy, bool IsConst = false );
132
+ QualType ReturnTy, bool IsConst = false ,
133
+ bool IsCtor = false )
134
+ : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr ),
135
+ IsConst (IsConst), IsCtor(IsCtor) {}
136
+
137
+ BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef NameStr,
138
+ QualType ReturnTy, bool IsConst = false ,
139
+ bool IsCtor = false );
133
140
BuiltinTypeMethodBuilder (const BuiltinTypeMethodBuilder &Other) = delete;
134
141
135
- ~BuiltinTypeMethodBuilder () { finalizeMethod (); }
142
+ ~BuiltinTypeMethodBuilder () { finalize (); }
136
143
137
144
BuiltinTypeMethodBuilder &
138
145
operator =(const BuiltinTypeMethodBuilder &Other) = delete ;
@@ -146,11 +153,18 @@ struct BuiltinTypeMethodBuilder {
146
153
template <typename TLHS, typename TRHS>
147
154
BuiltinTypeMethodBuilder &assign (TLHS LHS, TRHS RHS);
148
155
template <typename T> BuiltinTypeMethodBuilder &dereference (T Ptr);
149
- BuiltinTypeDeclBuilder &finalizeMethod ();
156
+ BuiltinTypeDeclBuilder &finalize ();
150
157
Expr *getResourceHandleExpr ();
151
158
152
159
private:
153
- void createMethodDecl ();
160
+ void createDecl ();
161
+
162
+ // Makes sure the declaration is created; should be called before any
163
+ // statement added to the body or when access to 'this' is needed.
164
+ void ensureCompleteDecl () {
165
+ if (!Method)
166
+ createDecl ();
167
+ }
154
168
};
155
169
156
170
TemplateParameterListBuilder::~TemplateParameterListBuilder () {
@@ -325,13 +339,24 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
325
339
}
326
340
327
341
BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB,
328
- StringRef Name ,
342
+ StringRef NameStr ,
329
343
QualType ReturnTy,
330
- bool IsConst)
331
- : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst) {
332
- const IdentifierInfo &II =
333
- DB.SemaRef .getASTContext ().Idents .get (Name, tok::TokenKind::identifier);
334
- NameInfo = DeclarationNameInfo (DeclarationName (&II), SourceLocation ());
344
+ bool IsConst, bool IsCtor)
345
+ : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst),
346
+ IsCtor (IsCtor) {
347
+
348
+ assert ((!NameStr.empty () || IsCtor) && " method needs a name" );
349
+ assert (((IsCtor && !IsConst) || !IsCtor) && " constructor cannot be const" );
350
+
351
+ ASTContext &AST = DB.SemaRef .getASTContext ();
352
+ if (IsCtor) {
353
+ Name = AST.DeclarationNames .getCXXConstructorName (
354
+ DB.Record ->getTypeForDecl ()->getCanonicalTypeUnqualified ());
355
+ } else {
356
+ const IdentifierInfo &II =
357
+ AST.Idents .get (NameStr, tok::TokenKind::identifier);
358
+ Name = DeclarationName (&II);
359
+ }
335
360
}
336
361
337
362
BuiltinTypeMethodBuilder &
@@ -344,33 +369,41 @@ BuiltinTypeMethodBuilder::addParam(StringRef Name, QualType Ty,
344
369
return *this ;
345
370
}
346
371
347
- void BuiltinTypeMethodBuilder::createMethodDecl () {
348
- assert (Method == nullptr && " Method already created" );
372
+ void BuiltinTypeMethodBuilder::createDecl () {
373
+ assert (Method == nullptr && " Method or constructor is already created" );
349
374
350
- // create method type
375
+ // create method or constructor type
351
376
ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
352
377
SmallVector<QualType> ParamTypes;
353
- for (MethodParam &MP : Params)
378
+ for (Param &MP : Params)
354
379
ParamTypes.emplace_back (MP.Ty );
355
380
356
381
FunctionProtoType::ExtProtoInfo ExtInfo;
357
382
if (IsConst)
358
383
ExtInfo.TypeQuals .addConst ();
359
384
360
- QualType MethodTy = AST.getFunctionType (ReturnTy, ParamTypes, ExtInfo);
361
-
362
- // create method decl
363
- auto *TSInfo = AST.getTrivialTypeSourceInfo (MethodTy, SourceLocation ());
364
- Method = CXXMethodDecl::Create (
365
- AST, DeclBuilder.Record , SourceLocation (), NameInfo, MethodTy, TSInfo,
366
- SC_None, false , false , ConstexprSpecKind::Unspecified, SourceLocation ());
385
+ QualType FuncTy = AST.getFunctionType (ReturnTy, ParamTypes, ExtInfo);
386
+
387
+ // create method or constructor decl
388
+ auto *TSInfo = AST.getTrivialTypeSourceInfo (FuncTy, SourceLocation ());
389
+ DeclarationNameInfo NameInfo = DeclarationNameInfo (Name, SourceLocation ());
390
+ if (IsCtor)
391
+ Method = CXXConstructorDecl::Create (
392
+ AST, DeclBuilder.Record , SourceLocation (), NameInfo, FuncTy, TSInfo,
393
+ ExplicitSpecifier (), false , true , false ,
394
+ ConstexprSpecKind::Unspecified);
395
+ else
396
+ Method =
397
+ CXXMethodDecl::Create (AST, DeclBuilder.Record , SourceLocation (),
398
+ NameInfo, FuncTy, TSInfo, SC_None, false , false ,
399
+ ConstexprSpecKind::Unspecified, SourceLocation ());
367
400
368
401
// create params & set them to the function prototype
369
402
SmallVector<ParmVarDecl *> ParmDecls;
370
403
auto FnProtoLoc =
371
404
Method->getTypeSourceInfo ()->getTypeLoc ().getAs <FunctionProtoTypeLoc>();
372
405
for (int I = 0 , E = Params.size (); I != E; I++) {
373
- MethodParam &MP = Params[I];
406
+ Param &MP = Params[I];
374
407
ParmVarDecl *Parm = ParmVarDecl::Create (
375
408
AST, Method->getDeclContext (), SourceLocation (), SourceLocation (),
376
409
&MP.NameII , MP.Ty ,
@@ -388,10 +421,7 @@ void BuiltinTypeMethodBuilder::createMethodDecl() {
388
421
}
389
422
390
423
Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr () {
391
- // The first statement added to a method or access to 'this' creates the
392
- // declaration.
393
- if (!Method)
394
- createMethodDecl ();
424
+ ensureCompleteDecl ();
395
425
396
426
ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
397
427
CXXThisExpr *This = CXXThisExpr::Create (
@@ -409,10 +439,7 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
409
439
std::array<Expr *, sizeof ...(ArgSpecs)> Args{
410
440
convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
411
441
412
- // The first statement added to a method or access to 'this` creates the
413
- // declaration.
414
- if (!Method)
415
- createMethodDecl ();
442
+ ensureCompleteDecl ();
416
443
417
444
ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
418
445
FunctionDecl *FD = lookupBuiltinFunction (DeclBuilder.SemaRef , BuiltinName);
@@ -453,11 +480,11 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
453
480
return *this ;
454
481
}
455
482
456
- BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalizeMethod () {
483
+ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize () {
457
484
assert (!DeclBuilder.Record ->isCompleteDefinition () &&
458
485
" record is already complete" );
459
- assert (Method != nullptr &&
460
- " method decl not created; are you missing a call to build the body? " );
486
+
487
+ ensureCompleteDecl ( );
461
488
462
489
if (!Method->hasBody ()) {
463
490
ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
@@ -599,27 +626,18 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
599
626
return *this ;
600
627
}
601
628
629
+ // Adds default constructor to the resource class:
630
+ // Resource::Resource()
602
631
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor () {
603
632
if (Record->isCompleteDefinition ())
604
633
return *this ;
605
- ASTContext &AST = Record->getASTContext ();
606
634
607
- QualType ConstructorType =
608
- AST.getFunctionType (AST.VoidTy , {}, FunctionProtoType::ExtProtoInfo ());
609
-
610
- CanQualType CanTy = Record->getTypeForDecl ()->getCanonicalTypeUnqualified ();
611
- DeclarationName Name = AST.DeclarationNames .getCXXConstructorName (CanTy);
612
- CXXConstructorDecl *Constructor = CXXConstructorDecl::Create (
613
- AST, Record, SourceLocation (),
614
- DeclarationNameInfo (Name, SourceLocation ()), ConstructorType,
615
- AST.getTrivialTypeSourceInfo (ConstructorType, SourceLocation ()),
616
- ExplicitSpecifier (), false , true , false , ConstexprSpecKind::Unspecified);
617
-
618
- Constructor->setBody (CompoundStmt::Create (
619
- AST, {}, FPOptionsOverride (), SourceLocation (), SourceLocation ()));
620
- Constructor->setAccess (AccessSpecifier::AS_public);
621
- Record->addDecl (Constructor);
622
- return *this ;
635
+ // FIXME: initialize handle to poison value; this can be added after
636
+ // resource constructor from binding is implemented, otherwise the handle
637
+ // value will get overwritten.
638
+ return BuiltinTypeMethodBuilder (*this , " " , SemaRef.getASTContext ().VoidTy ,
639
+ false , true )
640
+ .finalize ();
623
641
}
624
642
625
643
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators () {
@@ -713,7 +731,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addIncrementCounterMethod() {
713
731
SemaRef.getASTContext ().UnsignedIntTy )
714
732
.callBuiltin (" __builtin_hlsl_buffer_update_counter" , QualType (),
715
733
PH::Handle, getConstantIntExpr (1 ))
716
- .finalizeMethod ();
734
+ .finalize ();
717
735
}
718
736
719
737
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod () {
@@ -722,7 +740,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod() {
722
740
SemaRef.getASTContext ().UnsignedIntTy )
723
741
.callBuiltin (" __builtin_hlsl_buffer_update_counter" , QualType (),
724
742
PH::Handle, getConstantIntExpr (-1 ))
725
- .finalizeMethod ();
743
+ .finalize ();
726
744
}
727
745
728
746
BuiltinTypeDeclBuilder &
@@ -746,7 +764,7 @@ BuiltinTypeDeclBuilder::addHandleAccessFunction(DeclarationName &Name,
746
764
.callBuiltin (" __builtin_hlsl_resource_getpointer" , ElemPtrTy, PH::Handle,
747
765
PH::_0)
748
766
.dereference (PH::LastStmt)
749
- .finalizeMethod ();
767
+ .finalize ();
750
768
}
751
769
752
770
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addAppendMethod () {
@@ -761,7 +779,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addAppendMethod() {
761
779
AST.getPointerType (ElemTy), PH::Handle, PH::LastStmt)
762
780
.dereference (PH::LastStmt)
763
781
.assign (PH::LastStmt, PH::_0)
764
- .finalizeMethod ();
782
+ .finalize ();
765
783
}
766
784
767
785
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addConsumeMethod () {
@@ -774,7 +792,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addConsumeMethod() {
774
792
.callBuiltin (" __builtin_hlsl_resource_getpointer" ,
775
793
AST.getPointerType (ElemTy), PH::Handle, PH::LastStmt)
776
794
.dereference (PH::LastStmt)
777
- .finalizeMethod ();
795
+ .finalize ();
778
796
}
779
797
780
798
} // namespace hlsl
0 commit comments