Skip to content

Commit dcbbda4

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 dcbbda4

File tree

7 files changed

+354
-23
lines changed

7 files changed

+354
-23
lines changed

clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp

Lines changed: 150 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,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
483546
return *this;
484547
}
485548

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

@@ -510,11 +574,13 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
510574
Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
511575
SourceLocation(), SourceLocation()));
512576
Method->setLexicalDeclContext(DeclBuilder.Record);
513-
Method->setAccess(AccessSpecifier::AS_public);
577+
Method->setAccess(Access);
514578
Method->addAttr(AlwaysInlineAttr::CreateImplicit(
515579
AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
516580
DeclBuilder.Record->addDecl(Method);
517581
}
582+
if (OutMethod)
583+
*OutMethod = Method;
518584
return DeclBuilder;
519585
}
520586

@@ -619,7 +685,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
619685

620686
// Adds default constructor to the resource class:
621687
// Resource::Resource()
622-
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
688+
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor() {
623689
if (Record->isCompleteDefinition())
624690
return *this;
625691

@@ -633,6 +699,23 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
633699
.finalize();
634700
}
635701

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

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