@@ -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,80 +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
- // FIXME: Placeholder to make sure we return the correct type - create
222
- // field of element_type and return reference to it. This field will go
223
- // away once indexing into resources is properly implemented in
224
- // llvm/llvm-project#95956.
225
- if (Fields.count (" e" ) == 0 ) {
226
- addMemberVariable (" e" , ElemTy, {});
227
- }
228
- FieldDecl *ElemFieldDecl = Fields[" e" ];
229
-
230
- auto *This =
231
- CXXThisExpr::Create (AST, SourceLocation (),
232
- MethodDecl->getFunctionObjectParameterType (), true );
233
- Expr *ElemField = MemberExpr::CreateImplicit (
234
- AST, This, false , ElemFieldDecl, ElemFieldDecl->getType (), VK_LValue,
235
- OK_Ordinary);
236
- auto *Return =
237
- ReturnStmt::Create (AST, SourceLocation (), ElemField, nullptr );
238
-
239
- MethodDecl->setBody (CompoundStmt::Create (AST, {Return}, FPOptionsOverride (),
240
- SourceLocation (),
241
- SourceLocation ()));
242
- MethodDecl->setLexicalDeclContext (Record);
243
- MethodDecl->setAccess (AccessSpecifier::AS_public);
244
- MethodDecl->addAttr (AlwaysInlineAttr::CreateImplicit (
245
- AST, SourceRange (), AlwaysInlineAttr::CXX11_clang_always_inline));
246
- Record->addDecl (MethodDecl);
171
+ DeclarationName Subscript =
172
+ AST.DeclarationNames .getCXXOperatorName (OO_Subscript);
247
173
174
+ addHandleAccessFunction (Subscript, /* IsConst=*/ true , /* IsRef=*/ true );
175
+ addHandleAccessFunction (Subscript, /* IsConst=*/ false , /* IsRef=*/ true );
248
176
return *this ;
249
177
}
250
178
@@ -265,6 +193,13 @@ struct BuiltinTypeDeclBuilder {
265
193
return QualType ();
266
194
}
267
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
+
268
203
BuiltinTypeDeclBuilder &startDefinition () {
269
204
assert (!Record->isCompleteDefinition () && " record is already complete" );
270
205
Record->startDefinition ();
@@ -294,6 +229,8 @@ struct BuiltinTypeDeclBuilder {
294
229
// Builtin types methods
295
230
BuiltinTypeDeclBuilder &addIncrementCounterMethod ();
296
231
BuiltinTypeDeclBuilder &addDecrementCounterMethod ();
232
+ BuiltinTypeDeclBuilder &addHandleAccessFunction (DeclarationName &Name,
233
+ bool IsConst, bool IsRef);
297
234
};
298
235
299
236
struct TemplateParameterListBuilder {
@@ -453,7 +390,7 @@ struct TemplateParameterListBuilder {
453
390
// Builder for methods of builtin types. Allows adding methods to builtin types
454
391
// using the builder pattern like this:
455
392
//
456
- // BuiltinTypeMethodBuilder(Sema, RecordBuilder, "MethodName", ReturnType)
393
+ // BuiltinTypeMethodBuilder(RecordBuilder, "MethodName", ReturnType)
457
394
// .addParam("param_name", Type, InOutModifier)
458
395
// .callBuiltin("builtin_name", BuiltinParams...)
459
396
// .finalizeMethod();
@@ -486,6 +423,7 @@ struct BuiltinTypeMethodBuilder {
486
423
DeclarationNameInfo NameInfo;
487
424
QualType ReturnTy;
488
425
CXXMethodDecl *Method;
426
+ bool IsConst;
489
427
llvm::SmallVector<MethodParam> Params;
490
428
llvm::SmallVector<Stmt *> StmtsList;
491
429
@@ -508,11 +446,16 @@ struct BuiltinTypeMethodBuilder {
508
446
Expr *convertPlaceholder (Expr *E) { return E; }
509
447
510
448
public:
511
- BuiltinTypeMethodBuilder (Sema &S, BuiltinTypeDeclBuilder &DB, StringRef Name,
512
- QualType ReturnTy)
513
- : 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) {
514
457
const IdentifierInfo &II =
515
- S .getASTContext ().Idents .get (Name, tok::TokenKind::identifier);
458
+ DB. SemaRef .getASTContext ().Idents .get (Name, tok::TokenKind::identifier);
516
459
NameInfo = DeclarationNameInfo (DeclarationName (&II), SourceLocation ());
517
460
}
518
461
@@ -535,8 +478,12 @@ struct BuiltinTypeMethodBuilder {
535
478
SmallVector<QualType> ParamTypes;
536
479
for (MethodParam &MP : Params)
537
480
ParamTypes.emplace_back (MP.Ty );
538
- QualType MethodTy = AST.getFunctionType (ReturnTy, ParamTypes,
539
- FunctionProtoType::ExtProtoInfo ());
481
+
482
+ FunctionProtoType::ExtProtoInfo ExtInfo;
483
+ if (IsConst)
484
+ ExtInfo.TypeQuals .addConst ();
485
+
486
+ QualType MethodTy = AST.getFunctionType (ReturnTy, ParamTypes, ExtInfo);
540
487
541
488
// create method decl
542
489
auto *TSInfo = AST.getTrivialTypeSourceInfo (MethodTy, SourceLocation ());
@@ -586,7 +533,8 @@ struct BuiltinTypeMethodBuilder {
586
533
}
587
534
588
535
template <typename ... Ts>
589
- BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName, Ts... ArgSpecs) {
536
+ BuiltinTypeMethodBuilder &callBuiltin (StringRef BuiltinName,
537
+ QualType ReturnType, Ts... ArgSpecs) {
590
538
std::array<Expr *, sizeof ...(ArgSpecs)> Args{
591
539
convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
592
540
@@ -599,15 +547,32 @@ struct BuiltinTypeMethodBuilder {
599
547
FunctionDecl *FD = lookupBuiltinFunction (DeclBuilder.SemaRef , BuiltinName);
600
548
DeclRefExpr *DRE = DeclRefExpr::Create (
601
549
AST, NestedNameSpecifierLoc (), SourceLocation (), FD, false ,
602
- FD->getNameInfo (), FD->getType (), VK_PRValue);
550
+ FD->getNameInfo (), AST.BuiltinFnTy , VK_PRValue);
551
+
552
+ if (ReturnType.isNull ())
553
+ ReturnType = FD->getReturnType ();
603
554
604
- Expr *Call =
605
- CallExpr::Create (AST, DRE, Args, FD->getReturnType (), VK_PRValue,
606
- SourceLocation (), FPOptionsOverride ());
555
+ Expr *Call = CallExpr::Create (AST, DRE, Args, ReturnType, VK_PRValue,
556
+ SourceLocation (), FPOptionsOverride ());
607
557
StmtsList.push_back (Call);
608
558
return *this ;
609
559
}
610
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
+
611
576
BuiltinTypeDeclBuilder &finalizeMethod () {
612
577
assert (!DeclBuilder.Record ->isCompleteDefinition () &&
613
578
" record is already complete" );
@@ -621,11 +586,8 @@ struct BuiltinTypeMethodBuilder {
621
586
" nothing to return from non-void method" );
622
587
if (ReturnTy != AST.VoidTy ) {
623
588
if (Expr *LastExpr = dyn_cast<Expr>(StmtsList.back ())) {
624
- assert (AST.hasSameUnqualifiedType (
625
- isa<CallExpr>(LastExpr)
626
- ? cast<CallExpr>(LastExpr)->getCallReturnType (AST)
627
- : LastExpr->getType (),
628
- ReturnTy) &&
589
+ assert (AST.hasSameUnqualifiedType (LastExpr->getType (),
590
+ ReturnTy.getNonReferenceType ()) &&
629
591
" Return type of the last statement must match the return type "
630
592
" of the method" );
631
593
if (!isa<ReturnStmt>(LastExpr)) {
@@ -672,19 +634,43 @@ BuiltinTypeDeclBuilder::addSimpleTemplateParams(ArrayRef<StringRef> Names,
672
634
673
635
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addIncrementCounterMethod () {
674
636
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
675
- return BuiltinTypeMethodBuilder (SemaRef, *this , " IncrementCounter" ,
637
+ return BuiltinTypeMethodBuilder (*this , " IncrementCounter" ,
676
638
SemaRef.getASTContext ().UnsignedIntTy )
677
- .callBuiltin (" __builtin_hlsl_buffer_update_counter" , PH::Handle ,
678
- getConstantIntExpr (1 ))
639
+ .callBuiltin (" __builtin_hlsl_buffer_update_counter" , QualType () ,
640
+ PH::Handle, getConstantIntExpr (1 ))
679
641
.finalizeMethod ();
680
642
}
681
643
682
644
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod () {
683
645
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
684
- return BuiltinTypeMethodBuilder (SemaRef, *this , " DecrementCounter" ,
646
+ return BuiltinTypeMethodBuilder (*this , " DecrementCounter" ,
685
647
SemaRef.getASTContext ().UnsignedIntTy )
686
- .callBuiltin (" __builtin_hlsl_buffer_update_counter" , PH::Handle,
687
- 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 ()
688
674
.finalizeMethod ();
689
675
}
690
676
0 commit comments