Skip to content

Commit e5cfb97

Browse files
committed
[HLSL] Add static methods for resource initialization and a constructor from handle
Adds static methods `__createFromBinding` and `__createFromImplicitBinding` to resource classes. These methods will be used for resource initialization instead of the resource constructors that take binding information. Also adds a private resource constructor that takes an initialized resource handle. This constructor will be called from the static create methods.
1 parent 7a0d3ca commit e5cfb97

File tree

7 files changed

+353
-23
lines changed

7 files changed

+353
-23
lines changed

clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp

Lines changed: 149 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/AST/Expr.h"
2020
#include "clang/AST/Type.h"
2121
#include "clang/Basic/SourceLocation.h"
22+
#include "clang/Basic/Specifiers.h"
2223
#include "clang/Sema/Lookup.h"
2324
#include "clang/Sema/Sema.h"
2425
#include "clang/Sema/SemaHLSL.h"
@@ -110,8 +111,11 @@ struct BuiltinTypeMethodBuilder {
110111
CXXMethodDecl *Method;
111112
bool IsConst;
112113
bool IsCtor;
114+
AccessSpecifier Access;
115+
StorageClass SC;
113116
llvm::SmallVector<Param> Params;
114117
llvm::SmallVector<Stmt *> StmtsList;
118+
llvm::SmallVector<VarDecl *> LocalVars;
115119

116120
// Argument placeholders, inspired by std::placeholder. These are the indices
117121
// of arguments to forward to `callBuiltin` and other method builder methods.
@@ -120,7 +124,16 @@ struct BuiltinTypeMethodBuilder {
120124
// LastStmt - refers to the last statement in the method body; referencing
121125
// LastStmt will remove the statement from the method body since
122126
// 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+
};
124137

125138
Expr *convertPlaceholder(PlaceHolder PH);
126139
Expr *convertPlaceholder(Expr *E) { return E; }
@@ -130,13 +143,17 @@ struct BuiltinTypeMethodBuilder {
130143

131144
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
132145
QualType ReturnTy, bool IsConst = false,
133-
bool IsCtor = false)
146+
bool IsCtor = false,
147+
AccessSpecifier Access = AS_public,
148+
StorageClass SC = SC_None)
134149
: DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
135-
IsConst(IsConst), IsCtor(IsCtor) {}
150+
IsConst(IsConst), IsCtor(IsCtor), Access(Access), SC(SC) {}
136151

137152
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, StringRef NameStr,
138153
QualType ReturnTy, bool IsConst = false,
139-
bool IsCtor = false);
154+
bool IsCtor = false,
155+
AccessSpecifier Access = AS_public,
156+
StorageClass SC = SC_None);
140157
BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other) = delete;
141158

142159
~BuiltinTypeMethodBuilder() { finalize(); }
@@ -147,13 +164,15 @@ struct BuiltinTypeMethodBuilder {
147164
BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
148165
HLSLParamModifierAttr::Spelling Modifier =
149166
HLSLParamModifierAttr::Keyword_in);
167+
BuiltinTypeMethodBuilder &createLocalVar(StringRef Name, QualType Ty);
150168
template <typename... Ts>
151169
BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
152170
QualType ReturnType, Ts... ArgSpecs);
171+
template <typename T> BuiltinTypeMethodBuilder &callHandleCtor(T HandleExpr);
153172
template <typename TLHS, typename TRHS>
154173
BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
155174
template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
156-
BuiltinTypeDeclBuilder &finalize();
175+
BuiltinTypeDeclBuilder &finalize(CXXMethodDecl **OutMethod = nullptr);
157176
Expr *getResourceHandleExpr();
158177

159178
private:
@@ -328,19 +347,29 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
328347
}
329348

330349
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+
331361
ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
332362
return DeclRefExpr::Create(
333363
AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
334364
DeclarationNameInfo(ParamDecl->getDeclName(), SourceLocation()),
335365
ParamDecl->getType(), VK_PRValue);
336366
}
337367

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)
342371
: DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
343-
IsCtor(IsCtor) {
372+
IsCtor(IsCtor), Access(Access), SC(SC) {
344373

345374
assert((!NameStr.empty() || IsCtor) && "method needs a name");
346375
assert(((IsCtor && !IsConst) || !IsCtor) && "constructor cannot be const");
@@ -390,10 +419,9 @@ void BuiltinTypeMethodBuilder::createDecl() {
390419
ExplicitSpecifier(), false, true, false,
391420
ConstexprSpecKind::Unspecified);
392421
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());
397425

398426
// create params & set them to the function prototype
399427
SmallVector<ParmVarDecl *> ParmDecls;
@@ -431,15 +459,31 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
431459
OK_Ordinary);
432460
}
433461

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+
434478
template <typename... Ts>
435479
BuiltinTypeMethodBuilder &
436480
BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
437481
QualType ReturnType, Ts... ArgSpecs) {
482+
ensureCompleteDecl();
483+
438484
std::array<Expr *, sizeof...(ArgSpecs)> Args{
439485
convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
440486

441-
ensureCompleteDecl();
442-
443487
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
444488
FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
445489
DeclRefExpr *DRE = DeclRefExpr::Create(
@@ -459,6 +503,25 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
459503
return *this;
460504
}
461505

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+
462525
template <typename TLHS, typename TRHS>
463526
BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::assign(TLHS LHS, TRHS RHS) {
464527
Expr *LHSExpr = convertPlaceholder(LHS);
@@ -483,7 +546,7 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
483546
return *this;
484547
}
485548

486-
BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
549+
BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize(CXXMethodDecl **OutMethod) {
487550
assert(!DeclBuilder.Record->isCompleteDefinition() &&
488551
"record is already complete");
489552

@@ -510,11 +573,13 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
510573
Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
511574
SourceLocation(), SourceLocation()));
512575
Method->setLexicalDeclContext(DeclBuilder.Record);
513-
Method->setAccess(AccessSpecifier::AS_public);
576+
Method->setAccess(Access);
514577
Method->addAttr(AlwaysInlineAttr::CreateImplicit(
515578
AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
516579
DeclBuilder.Record->addDecl(Method);
517580
}
581+
if (OutMethod)
582+
*OutMethod = Method;
518583
return DeclBuilder;
519584
}
520585

@@ -619,7 +684,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
619684

620685
// Adds default constructor to the resource class:
621686
// Resource::Resource()
622-
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
687+
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor() {
623688
if (Record->isCompleteDefinition())
624689
return *this;
625690

@@ -633,6 +698,23 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
633698
.finalize();
634699
}
635700

701+
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleConstructor() {
702+
if (Record->isCompleteDefinition())
703+
return *this;
704+
705+
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
706+
ASTContext &AST = SemaRef.getASTContext();
707+
QualType HandleType = getResourceHandleField()->getType();
708+
CXXMethodDecl *OutMethod = nullptr;
709+
710+
BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true, AS_public)
711+
.addParam("handle", HandleType)
712+
.assign(PH::Handle, PH::_0)
713+
.finalize(&OutMethod);
714+
HandleCtor = cast<CXXConstructorDecl>(OutMethod);
715+
return *this;
716+
}
717+
636718
BuiltinTypeDeclBuilder &
637719
BuiltinTypeDeclBuilder::addHandleConstructorFromBinding() {
638720
if (Record->isCompleteDefinition())
@@ -676,6 +758,54 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
676758
.finalize();
677759
}
678760

761+
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
762+
if (Record->isCompleteDefinition())
763+
return *this;
764+
765+
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
766+
ASTContext &AST = SemaRef.getASTContext();
767+
QualType HandleType = getResourceHandleField()->getType();
768+
QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
769+
770+
return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
771+
false, false, AS_public, SC_Static)
772+
.addParam("registerNo", AST.UnsignedIntTy)
773+
.addParam("spaceNo", AST.UnsignedIntTy)
774+
.addParam("range", AST.IntTy)
775+
.addParam("index", AST.UnsignedIntTy)
776+
.addParam("name", AST.getPointerType(AST.CharTy.withConst()))
777+
.createLocalVar("tmp", HandleType)
778+
.callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
779+
PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
780+
.callHandleCtor(PH::LastStmt)
781+
.finalize();
782+
}
783+
784+
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
785+
if (Record->isCompleteDefinition())
786+
return *this;
787+
788+
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
789+
ASTContext &AST = SemaRef.getASTContext();
790+
QualType HandleType = getResourceHandleField()->getType();
791+
QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
792+
793+
return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
794+
RecordType, false, false, AS_public,
795+
SC_Static)
796+
.addParam("orderId", AST.UnsignedIntTy)
797+
.addParam("spaceNo", AST.UnsignedIntTy)
798+
.addParam("range", AST.IntTy)
799+
.addParam("index", AST.UnsignedIntTy)
800+
.addParam("name", AST.getPointerType(AST.CharTy.withConst()))
801+
.createLocalVar("tmp", HandleType)
802+
.callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
803+
HandleType, PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3,
804+
PH::_4)
805+
.callHandleCtor(PH::LastStmt)
806+
.finalize();
807+
}
808+
679809
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
680810
ASTContext &AST = Record->getASTContext();
681811
DeclarationName Subscript =

clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace clang {
2525
class ClassTemplateDecl;
2626
class NamespaceDecl;
2727
class CXXRecordDecl;
28+
class CXXConstructorDecl;
2829
class FieldDecl;
2930

3031
namespace hlsl {
@@ -52,6 +53,7 @@ class BuiltinTypeDeclBuilder {
5253
ClassTemplateDecl *PrevTemplate = nullptr;
5354
NamespaceDecl *HLSLNamespace = nullptr;
5455
llvm::StringMap<FieldDecl *> Fields;
56+
CXXConstructorDecl *HandleCtor = nullptr;
5557

5658
public:
5759
friend struct TemplateParameterListBuilder;
@@ -77,10 +79,15 @@ class BuiltinTypeDeclBuilder {
7779
BuiltinTypeDeclBuilder &addArraySubscriptOperators();
7880

7981
// Builtin types constructors
80-
BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
82+
BuiltinTypeDeclBuilder &addDefaultConstructor();
83+
BuiltinTypeDeclBuilder &addHandleConstructor();
8184
BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
8285
BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
8386

87+
// Static create methods
88+
BuiltinTypeDeclBuilder &addCreateFromBinding();
89+
BuiltinTypeDeclBuilder &addCreateFromImplicitBinding();
90+
8491
// Builtin types methods
8592
BuiltinTypeDeclBuilder &addLoadMethods();
8693
BuiltinTypeDeclBuilder &addIncrementCounterMethod();

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,10 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
131131
bool RawBuffer) {
132132
return BuiltinTypeDeclBuilder(S, Decl)
133133
.addHandleMember(RC, IsROV, RawBuffer)
134-
.addDefaultHandleConstructor()
134+
.addDefaultConstructor()
135+
.addHandleConstructor()
136+
.addCreateFromBinding()
137+
.addCreateFromImplicitBinding()
135138
.addHandleConstructorFromBinding()
136139
.addHandleConstructorFromImplicitBinding();
137140
}

0 commit comments

Comments
 (0)