@@ -123,12 +123,8 @@ struct BuiltinTypeDeclBuilder {
123
123
assert (!Record->isCompleteDefinition () && " record is already complete" );
124
124
125
125
ASTContext &Ctx = SemaRef.getASTContext ();
126
- TypeSourceInfo *ElementTypeInfo = nullptr ;
127
-
128
- QualType ElemTy = Ctx.Char8Ty ;
129
- if (Template)
130
- ElemTy = getFirstTemplateTypeParam ();
131
- ElementTypeInfo = Ctx.getTrivialTypeSourceInfo (ElemTy, SourceLocation ());
126
+ TypeSourceInfo *ElementTypeInfo =
127
+ Ctx.getTrivialTypeSourceInfo (getHandleElementType (), SourceLocation ());
132
128
133
129
// add handle member with resource type attributes
134
130
QualType AttributedResTy = QualType ();
@@ -171,90 +167,12 @@ struct BuiltinTypeDeclBuilder {
171
167
}
172
168
173
169
BuiltinTypeDeclBuilder &addArraySubscriptOperators () {
174
- addArraySubscriptOperator (true );
175
- addArraySubscriptOperator (false );
176
- return *this ;
177
- }
178
-
179
- BuiltinTypeDeclBuilder &addArraySubscriptOperator (bool IsConst) {
180
- assert (!Record->isCompleteDefinition () && " record is already complete" );
181
-
182
170
ASTContext &AST = Record->getASTContext ();
183
- QualType ElemTy = AST.Char8Ty ;
184
- if (Template)
185
- ElemTy = getFirstTemplateTypeParam ();
186
- QualType ReturnTy = ElemTy;
187
-
188
- FunctionProtoType::ExtProtoInfo ExtInfo;
189
-
190
- // Subscript operators return references to elements, const makes the
191
- // reference and method const so that the underlying data is not mutable.
192
- if (IsConst) {
193
- ExtInfo.TypeQuals .addConst ();
194
- ReturnTy.addConst ();
195
- }
196
- ReturnTy = AST.getLValueReferenceType (ReturnTy);
197
-
198
- QualType MethodTy =
199
- AST.getFunctionType (ReturnTy, {AST.UnsignedIntTy }, ExtInfo);
200
- auto *TSInfo = AST.getTrivialTypeSourceInfo (MethodTy, SourceLocation ());
201
- auto *MethodDecl = CXXMethodDecl::Create (
202
- AST, Record, SourceLocation (),
203
- DeclarationNameInfo (
204
- AST.DeclarationNames .getCXXOperatorName (OO_Subscript),
205
- SourceLocation ()),
206
- MethodTy, TSInfo, SC_None, false , false , ConstexprSpecKind::Unspecified,
207
- SourceLocation ());
208
-
209
- IdentifierInfo &II = AST.Idents .get (" Idx" , tok::TokenKind::identifier);
210
- auto *IdxParam = ParmVarDecl::Create (
211
- AST, MethodDecl->getDeclContext (), SourceLocation (), SourceLocation (),
212
- &II, AST.UnsignedIntTy ,
213
- AST.getTrivialTypeSourceInfo (AST.UnsignedIntTy , SourceLocation ()),
214
- SC_None, nullptr );
215
- MethodDecl->setParams ({IdxParam});
216
-
217
- // Also add the parameter to the function prototype.
218
- auto FnProtoLoc = TSInfo->getTypeLoc ().getAs <FunctionProtoTypeLoc>();
219
- FnProtoLoc.setParam (0 , IdxParam);
220
-
221
- auto *This =
222
- CXXThisExpr::Create (AST, SourceLocation (),
223
- MethodDecl->getFunctionObjectParameterType (), true );
224
- FieldDecl *Handle = Fields[" __handle" ];
225
- auto *HandleExpr = MemberExpr::CreateImplicit (
226
- AST, This, false , Handle, Handle->getType (), VK_LValue, OK_Ordinary);
227
-
228
- auto *IndexExpr = DeclRefExpr::Create (
229
- AST, NestedNameSpecifierLoc (), SourceLocation (), IdxParam, false ,
230
- DeclarationNameInfo (IdxParam->getDeclName (), SourceLocation ()),
231
- AST.UnsignedIntTy , VK_PRValue);
232
-
233
- FunctionDecl *FD =
234
- lookupBuiltinFunction (SemaRef, " __builtin_hlsl_resource_getpointer" );
235
- DeclRefExpr *Builtin = DeclRefExpr::Create (
236
- AST, NestedNameSpecifierLoc (), SourceLocation (), FD, false ,
237
- FD->getNameInfo (), AST.BuiltinFnTy , VK_PRValue);
238
-
239
- // TODO: Map to an hlsl_device address space.
240
- QualType ElemPtrTy = AST.getPointerType (ElemTy);
241
- Expr *Call =
242
- CallExpr::Create (AST, Builtin, {HandleExpr, IndexExpr}, ElemPtrTy,
243
- VK_PRValue, SourceLocation (), FPOptionsOverride ());
244
- Expr *Deref = UnaryOperator::Create (
245
- AST, Call, UO_Deref, ElemTy, VK_PRValue, OK_Ordinary, SourceLocation (),
246
- /* CanOverflow=*/ false , FPOptionsOverride ());
247
- auto *Return = ReturnStmt::Create (AST, SourceLocation (), Deref, nullptr );
248
-
249
- MethodDecl->setBody (CompoundStmt::Create (AST, {Return}, FPOptionsOverride (),
250
- SourceLocation (),
251
- SourceLocation ()));
252
- MethodDecl->setLexicalDeclContext (Record);
253
- MethodDecl->setAccess (AccessSpecifier::AS_public);
254
- MethodDecl->addAttr (AlwaysInlineAttr::CreateImplicit (
255
- AST, SourceRange (), AlwaysInlineAttr::CXX11_clang_always_inline));
256
- Record->addDecl (MethodDecl);
171
+ DeclarationName Subscript =
172
+ AST.DeclarationNames .getCXXOperatorName (OO_Subscript);
257
173
174
+ addHandleAccessFunction (Subscript, /* IsConst=*/ true , /* IsRef=*/ true );
175
+ addHandleAccessFunction (Subscript, /* IsConst=*/ false , /* IsRef=*/ true );
258
176
return *this ;
259
177
}
260
178
@@ -275,6 +193,13 @@ struct BuiltinTypeDeclBuilder {
275
193
return QualType ();
276
194
}
277
195
196
+ QualType getHandleElementType () {
197
+ if (Template)
198
+ return getFirstTemplateTypeParam ();
199
+ // TODO: Should we default to VoidTy? Using `i8` is arguably ambiguous.
200
+ return SemaRef.getASTContext ().Char8Ty ;
201
+ }
202
+
278
203
BuiltinTypeDeclBuilder &startDefinition () {
279
204
assert (!Record->isCompleteDefinition () && " record is already complete" );
280
205
Record->startDefinition ();
@@ -304,6 +229,8 @@ struct BuiltinTypeDeclBuilder {
304
229
// Builtin types methods
305
230
BuiltinTypeDeclBuilder &addIncrementCounterMethod ();
306
231
BuiltinTypeDeclBuilder &addDecrementCounterMethod ();
232
+ BuiltinTypeDeclBuilder &addHandleAccessFunction (DeclarationName &Name,
233
+ bool IsConst, bool IsRef);
307
234
};
308
235
309
236
struct TemplateParameterListBuilder {
@@ -463,7 +390,7 @@ struct TemplateParameterListBuilder {
463
390
// Builder for methods of builtin types. Allows adding methods to builtin types
464
391
// using the builder pattern like this:
465
392
//
466
- // BuiltinTypeMethodBuilder(Sema, RecordBuilder, "MethodName", ReturnType)
393
+ // BuiltinTypeMethodBuilder(RecordBuilder, "MethodName", ReturnType)
467
394
// .addParam("param_name", Type, InOutModifier)
468
395
// .callBuiltin("builtin_name", BuiltinParams...)
469
396
// .finalizeMethod();
@@ -496,6 +423,7 @@ struct BuiltinTypeMethodBuilder {
496
423
DeclarationNameInfo NameInfo;
497
424
QualType ReturnTy;
498
425
CXXMethodDecl *Method;
426
+ bool IsConst;
499
427
llvm::SmallVector<MethodParam> Params;
500
428
llvm::SmallVector<Stmt *> StmtsList;
501
429
@@ -518,11 +446,16 @@ struct BuiltinTypeMethodBuilder {
518
446
Expr *convertPlaceholder (Expr *E) { return E; }
519
447
520
448
public:
521
- BuiltinTypeMethodBuilder (Sema &S, BuiltinTypeDeclBuilder &DB, StringRef Name,
522
- QualType ReturnTy)
523
- : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ) {
449
+ BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
450
+ QualType ReturnTy, bool IsConst = false )
451
+ : DeclBuilder(DB), NameInfo(DeclarationNameInfo(Name, SourceLocation())),
452
+ ReturnTy (ReturnTy), Method(nullptr ), IsConst(IsConst) {}
453
+
454
+ BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef Name,
455
+ QualType ReturnTy, bool IsConst = false )
456
+ : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst) {
524
457
const IdentifierInfo &II =
525
- S .getASTContext ().Idents .get (Name, tok::TokenKind::identifier);
458
+ DB. SemaRef .getASTContext ().Idents .get (Name, tok::TokenKind::identifier);
526
459
NameInfo = DeclarationNameInfo (DeclarationName (&II), SourceLocation ());
527
460
}
528
461
@@ -545,8 +478,12 @@ struct BuiltinTypeMethodBuilder {
545
478
SmallVector<QualType> ParamTypes;
546
479
for (MethodParam &MP : Params)
547
480
ParamTypes.emplace_back (MP.Ty );
548
- QualType MethodTy = AST.getFunctionType (ReturnTy, ParamTypes,
549
- FunctionProtoType::ExtProtoInfo ());
481
+
482
+ FunctionProtoType::ExtProtoInfo ExtInfo;
483
+ if (IsConst)
484
+ ExtInfo.TypeQuals .addConst ();
485
+
486
+ QualType MethodTy = AST.getFunctionType (ReturnTy, ParamTypes, ExtInfo);
550
487
551
488
// create method decl
552
489
auto *TSInfo = AST.getTrivialTypeSourceInfo (MethodTy, SourceLocation ());
@@ -596,7 +533,8 @@ struct BuiltinTypeMethodBuilder {
596
533
}
597
534
598
535
template <typename ... Ts>
599
- BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName, Ts... ArgSpecs) {
536
+ BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName,
537
+ QualType ReturnType, Ts... ArgSpecs) {
600
538
std::array<Expr *, sizeof ...(ArgSpecs)> Args{
601
539
convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
602
540
@@ -609,15 +547,32 @@ struct BuiltinTypeMethodBuilder {
609
547
FunctionDecl *FD = lookupBuiltinFunction (DeclBuilder.SemaRef , BuiltinName);
610
548
DeclRefExpr *DRE = DeclRefExpr::Create (
611
549
AST, NestedNameSpecifierLoc (), SourceLocation (), FD, false ,
612
- FD->getNameInfo (), FD->getType (), VK_PRValue);
550
+ FD->getNameInfo (), AST.BuiltinFnTy , VK_PRValue);
551
+
552
+ if (ReturnType.isNull ())
553
+ ReturnType = FD->getReturnType ();
613
554
614
- Expr *Call =
615
- CallExpr::Create (AST, DRE, Args, FD->getReturnType (), VK_PRValue,
616
- SourceLocation (), FPOptionsOverride ());
555
+ Expr *Call = CallExpr::Create (AST, DRE, Args, ReturnType, VK_PRValue,
556
+ SourceLocation (), FPOptionsOverride ());
617
557
StmtsList.push_back (Call);
618
558
return *this ;
619
559
}
620
560
561
+ BuiltinTypeMethodBuilder &dereference () {
562
+ assert (!StmtsList.empty () && " Nothing to dereference" );
563
+ ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
564
+
565
+ Expr *LastExpr = dyn_cast<Expr>(StmtsList.back ());
566
+ assert (LastExpr && " No expression to dereference" );
567
+ Expr *Deref = UnaryOperator::Create (
568
+ AST, LastExpr, UO_Deref, LastExpr->getType ()->getPointeeType (),
569
+ VK_PRValue, OK_Ordinary, SourceLocation (),
570
+ /* CanOverflow=*/ false , FPOptionsOverride ());
571
+ StmtsList.pop_back ();
572
+ StmtsList.push_back (Deref);
573
+ return *this ;
574
+ }
575
+
621
576
BuiltinTypeDeclBuilder &finalizeMethod () {
622
577
assert (!DeclBuilder.Record ->isCompleteDefinition () &&
623
578
" record is already complete" );
@@ -631,11 +586,8 @@ struct BuiltinTypeMethodBuilder {
631
586
" nothing to return from non-void method" );
632
587
if (ReturnTy != AST.VoidTy ) {
633
588
if (Expr *LastExpr = dyn_cast<Expr>(StmtsList.back ())) {
634
- assert (AST.hasSameUnqualifiedType (
635
- isa<CallExpr>(LastExpr)
636
- ? cast<CallExpr>(LastExpr)->getCallReturnType (AST)
637
- : LastExpr->getType (),
638
- ReturnTy) &&
589
+ assert (AST.hasSameUnqualifiedType (LastExpr->getType (),
590
+ ReturnTy.getNonReferenceType ()) &&
639
591
" Return type of the last statement must match the return type "
640
592
" of the method" );
641
593
if (!isa<ReturnStmt>(LastExpr)) {
@@ -682,19 +634,43 @@ BuiltinTypeDeclBuilder::addSimpleTemplateParams(ArrayRef<StringRef> Names,
682
634
683
635
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addIncrementCounterMethod () {
684
636
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
685
- return BuiltinTypeMethodBuilder (SemaRef, *this , " IncrementCounter" ,
637
+ return BuiltinTypeMethodBuilder (*this , " IncrementCounter" ,
686
638
SemaRef.getASTContext ().UnsignedIntTy )
687
- .callBuiltin (" __builtin_hlsl_buffer_update_counter" , PH::Handle ,
688
- getConstantIntExpr (1 ))
639
+ .callBuiltin (" __builtin_hlsl_buffer_update_counter" , QualType () ,
640
+ PH::Handle, getConstantIntExpr (1 ))
689
641
.finalizeMethod ();
690
642
}
691
643
692
644
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod () {
693
645
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
694
- return BuiltinTypeMethodBuilder (SemaRef, *this , " DecrementCounter" ,
646
+ return BuiltinTypeMethodBuilder (*this , " DecrementCounter" ,
695
647
SemaRef.getASTContext ().UnsignedIntTy )
696
- .callBuiltin (" __builtin_hlsl_buffer_update_counter" , PH::Handle,
697
- getConstantIntExpr (-1 ))
648
+ .callBuiltin (" __builtin_hlsl_buffer_update_counter" , QualType (),
649
+ PH::Handle, getConstantIntExpr (-1 ))
650
+ .finalizeMethod ();
651
+ }
652
+
653
+ BuiltinTypeDeclBuilder &
654
+ BuiltinTypeDeclBuilder::addHandleAccessFunction (DeclarationName &Name,
655
+ bool IsConst, bool IsRef) {
656
+ assert (!Record->isCompleteDefinition () && " record is already complete" );
657
+ ASTContext &AST = SemaRef.getASTContext ();
658
+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
659
+
660
+ QualType ElemTy = getHandleElementType ();
661
+ // TODO: Map to an hlsl_device address space.
662
+ QualType ElemPtrTy = AST.getPointerType (ElemTy);
663
+ QualType ReturnTy = ElemTy;
664
+ if (IsConst)
665
+ ReturnTy.addConst ();
666
+ if (IsRef)
667
+ ReturnTy = AST.getLValueReferenceType (ReturnTy);
668
+
669
+ return BuiltinTypeMethodBuilder (*this , Name, ReturnTy, IsConst)
670
+ .addParam (" Index" , AST.UnsignedIntTy )
671
+ .callBuiltin (" __builtin_hlsl_resource_getpointer" , ElemPtrTy, PH::Handle,
672
+ PH::_0)
673
+ .dereference ()
698
674
.finalizeMethod ();
699
675
}
700
676
0 commit comments