Skip to content

Commit 47b41c8

Browse files
committed
[HLSL] Create default resource constructor with BuiltinTypeMethodBuilder
1 parent 443eb3d commit 47b41c8

File tree

1 file changed

+72
-54
lines changed

1 file changed

+72
-54
lines changed

clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp

Lines changed: 72 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,24 @@ struct TemplateParameterListBuilder {
8989
// statement (unless the last statement is already a ReturnStmt).
9090
struct BuiltinTypeMethodBuilder {
9191
private:
92-
struct MethodParam {
92+
struct Param {
9393
const IdentifierInfo &NameII;
9494
QualType Ty;
9595
HLSLParamModifierAttr::Spelling Modifier;
96-
MethodParam(const IdentifierInfo &NameII, QualType Ty,
97-
HLSLParamModifierAttr::Spelling Modifier)
96+
Param(const IdentifierInfo &NameII, QualType Ty,
97+
HLSLParamModifierAttr::Spelling Modifier)
9898
: NameII(NameII), Ty(Ty), Modifier(Modifier) {}
9999
};
100100

101101
BuiltinTypeDeclBuilder &DeclBuilder;
102-
DeclarationNameInfo NameInfo;
102+
DeclarationName Name;
103103
QualType ReturnTy;
104+
// method or constructor declaration (CXXConstructorDecl derives from
105+
// CXXMethodDecl)
104106
CXXMethodDecl *Method;
105107
bool IsConst;
106-
llvm::SmallVector<MethodParam> Params;
108+
bool IsConstructor;
109+
llvm::SmallVector<Param> Params;
107110
llvm::SmallVector<Stmt *> StmtsList;
108111

109112
// Argument placeholders, inspired by std::placeholder. These are the indices
@@ -122,12 +125,14 @@ struct BuiltinTypeMethodBuilder {
122125
friend BuiltinTypeDeclBuilder;
123126

124127
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
125-
QualType ReturnTy, bool IsConst = false)
126-
: DeclBuilder(DB), NameInfo(DeclarationNameInfo(Name, SourceLocation())),
127-
ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst) {}
128-
129-
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, StringRef Name,
130-
QualType ReturnTy, bool IsConst = false);
128+
QualType ReturnTy, bool IsConst = false,
129+
bool IsConstructor = false)
130+
: DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
131+
IsConst(IsConst), IsConstructor(IsConstructor) {}
132+
133+
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, StringRef NameStr,
134+
QualType ReturnTy, bool IsConst = false,
135+
bool IsConstructor = false);
131136
BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other) = delete;
132137

133138
~BuiltinTypeMethodBuilder() { finalizeMethod(); }
@@ -148,7 +153,14 @@ struct BuiltinTypeMethodBuilder {
148153
Expr *getResourceHandleExpr();
149154

150155
private:
151-
void createMethodDecl();
156+
void createDecl();
157+
158+
// Makes sure the declaration is created; should be called before any
159+
// statement added or when access to 'this' is needed.
160+
void ensureCompleteDecl() {
161+
if (!Method)
162+
createDecl();
163+
}
152164
};
153165

154166
TemplateParameterListBuilder::~TemplateParameterListBuilder() {
@@ -323,13 +335,26 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
323335
}
324336

325337
BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB,
326-
StringRef Name,
338+
StringRef NameStr,
327339
QualType ReturnTy,
328-
bool IsConst)
329-
: DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst) {
330-
const IdentifierInfo &II =
331-
DB.SemaRef.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
332-
NameInfo = DeclarationNameInfo(DeclarationName(&II), SourceLocation());
340+
bool IsConst,
341+
bool IsConstructor)
342+
: DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
343+
IsConstructor(IsConstructor) {
344+
345+
assert((!NameStr.empty() || IsConstructor) && "method needs a name");
346+
assert(((IsConstructor && !IsConst) || !IsConstructor) &&
347+
"constructor cannot be const");
348+
349+
ASTContext &AST = DB.SemaRef.getASTContext();
350+
if (IsConstructor) {
351+
Name = AST.DeclarationNames.getCXXConstructorName(
352+
DB.Record->getTypeForDecl()->getCanonicalTypeUnqualified());
353+
} else {
354+
const IdentifierInfo &II =
355+
AST.Idents.get(NameStr, tok::TokenKind::identifier);
356+
Name = DeclarationName(&II);
357+
}
333358
}
334359

335360
BuiltinTypeMethodBuilder &
@@ -342,13 +367,13 @@ BuiltinTypeMethodBuilder::addParam(StringRef Name, QualType Ty,
342367
return *this;
343368
}
344369

345-
void BuiltinTypeMethodBuilder::createMethodDecl() {
346-
assert(Method == nullptr && "Method already created");
370+
void BuiltinTypeMethodBuilder::createDecl() {
371+
assert(Method == nullptr && "Method or constructor is already created");
347372

348-
// create method type
373+
// create method or constructor type
349374
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
350375
SmallVector<QualType> ParamTypes;
351-
for (MethodParam &MP : Params)
376+
for (Param &MP : Params)
352377
ParamTypes.emplace_back(MP.Ty);
353378

354379
FunctionProtoType::ExtProtoInfo ExtInfo;
@@ -357,18 +382,26 @@ void BuiltinTypeMethodBuilder::createMethodDecl() {
357382

358383
QualType MethodTy = AST.getFunctionType(ReturnTy, ParamTypes, ExtInfo);
359384

360-
// create method decl
385+
// create method or constructor decl
361386
auto *TSInfo = AST.getTrivialTypeSourceInfo(MethodTy, SourceLocation());
362-
Method = CXXMethodDecl::Create(
363-
AST, DeclBuilder.Record, SourceLocation(), NameInfo, MethodTy, TSInfo,
364-
SC_None, false, false, ConstexprSpecKind::Unspecified, SourceLocation());
387+
DeclarationNameInfo NameInfo = DeclarationNameInfo(Name, SourceLocation());
388+
if (IsConstructor)
389+
Method = CXXConstructorDecl::Create(
390+
AST, DeclBuilder.Record, SourceLocation(), NameInfo, MethodTy, TSInfo,
391+
ExplicitSpecifier(), false, true, false,
392+
ConstexprSpecKind::Unspecified);
393+
else
394+
Method =
395+
CXXMethodDecl::Create(AST, DeclBuilder.Record, SourceLocation(),
396+
NameInfo, MethodTy, TSInfo, SC_None, false, false,
397+
ConstexprSpecKind::Unspecified, SourceLocation());
365398

366399
// create params & set them to the function prototype
367400
SmallVector<ParmVarDecl *> ParmDecls;
368401
auto FnProtoLoc =
369402
Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
370403
for (int I = 0, E = Params.size(); I != E; I++) {
371-
MethodParam &MP = Params[I];
404+
Param &MP = Params[I];
372405
ParmVarDecl *Parm = ParmVarDecl::Create(
373406
AST, Method->getDeclContext(), SourceLocation(), SourceLocation(),
374407
&MP.NameII, MP.Ty,
@@ -386,10 +419,7 @@ void BuiltinTypeMethodBuilder::createMethodDecl() {
386419
}
387420

388421
Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
389-
// The first statement added to a method or access to 'this' creates the
390-
// declaration.
391-
if (!Method)
392-
createMethodDecl();
422+
ensureCompleteDecl();
393423

394424
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
395425
CXXThisExpr *This = CXXThisExpr::Create(
@@ -407,10 +437,7 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
407437
std::array<Expr *, sizeof...(ArgSpecs)> Args{
408438
convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
409439

410-
// The first statement added to a method or access to 'this` creates the
411-
// declaration.
412-
if (!Method)
413-
createMethodDecl();
440+
ensureCompleteDecl();
414441

415442
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
416443
FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
@@ -454,8 +481,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
454481
BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalizeMethod() {
455482
assert(!DeclBuilder.Record->isCompleteDefinition() &&
456483
"record is already complete");
457-
assert(Method != nullptr &&
458-
"method decl not created; are you missing a call to build the body?");
484+
485+
ensureCompleteDecl();
459486

460487
if (!Method->hasBody()) {
461488
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
@@ -600,27 +627,18 @@ BuiltinTypeDeclBuilder::addHandleMember(ResourceClass RC, ResourceKind RK,
600627
return *this;
601628
}
602629

630+
// Adds default constructor to the resource class:
631+
// Resource::Resource()
603632
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
604633
if (Record->isCompleteDefinition())
605634
return *this;
606-
ASTContext &AST = Record->getASTContext();
607635

608-
QualType ConstructorType =
609-
AST.getFunctionType(AST.VoidTy, {}, FunctionProtoType::ExtProtoInfo());
610-
611-
CanQualType CanTy = Record->getTypeForDecl()->getCanonicalTypeUnqualified();
612-
DeclarationName Name = AST.DeclarationNames.getCXXConstructorName(CanTy);
613-
CXXConstructorDecl *Constructor = CXXConstructorDecl::Create(
614-
AST, Record, SourceLocation(),
615-
DeclarationNameInfo(Name, SourceLocation()), ConstructorType,
616-
AST.getTrivialTypeSourceInfo(ConstructorType, SourceLocation()),
617-
ExplicitSpecifier(), false, true, false, ConstexprSpecKind::Unspecified);
618-
619-
Constructor->setBody(CompoundStmt::Create(
620-
AST, {}, FPOptionsOverride(), SourceLocation(), SourceLocation()));
621-
Constructor->setAccess(AccessSpecifier::AS_public);
622-
Record->addDecl(Constructor);
623-
return *this;
636+
// FIXME: initialize handle to poison value; this can be added after
637+
// resource constructor from binding is implemented, otherwise the handle
638+
// value will get overwritten.
639+
return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
640+
false, true)
641+
.finalizeMethod();
624642
}
625643

626644
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {

0 commit comments

Comments
 (0)