20#include "llvm/Frontend/HLSL/HLSLResource.h"
25using namespace llvm::hlsl;
29struct TemplateParameterListBuilder;
31struct BuiltinTypeDeclBuilder {
36 llvm::StringMap<FieldDecl *> Fields;
40 Template =
Record->getDescribedClassTemplate();
52 if (
auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
53 PrevDecl = TD->getTemplatedDecl();
56 PrevDecl = dyn_cast<CXXRecordDecl>(Found);
57 assert(PrevDecl &&
"Unexpected lookup result type.");
69 Record->setLexicalDeclContext(HLSLNamespace);
70 Record->setHasExternalLexicalStorage();
75 FinalAttr::Keyword_final));
78 ~BuiltinTypeDeclBuilder() {
79 if (HLSLNamespace && !Template &&
Record->getDeclContext() == HLSLNamespace)
83 BuiltinTypeDeclBuilder &
86 if (
Record->isCompleteDefinition())
88 assert(
Record->isBeingDefined() &&
89 "Definition must be started before adding members!");
97 nullptr,
false, InClassInitStyle::ICIS_NoInit);
98 Field->setAccess(Access);
99 Field->setImplicit(
true);
101 Fields[Name] =
Field;
105 BuiltinTypeDeclBuilder &
106 addHandleMember(
AccessSpecifier Access = AccessSpecifier::AS_private) {
107 if (
Record->isCompleteDefinition())
111 if (
const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
113 Ty =
Record->getASTContext().getPointerType(
114 QualType(TTD->getTypeForDecl(), 0));
116 return addMemberVariable(
"h", Ty, Access);
119 BuiltinTypeDeclBuilder &
120 annotateResourceClass(HLSLResourceAttr::ResourceClass RC,
121 HLSLResourceAttr::ResourceKind RK) {
122 if (
Record->isCompleteDefinition())
125 HLSLResourceAttr::CreateImplicit(
Record->getASTContext(), RC, RK));
137 assert(R.isSingleResult() &&
138 "Since this is a builtin it should always resolve!");
139 auto *VD = cast<ValueDecl>(R.getFoundDecl());
145 static Expr *emitResourceClassExpr(
ASTContext &AST, ResourceClass RC) {
149 static_cast<uint8_t
>(RC)),
153 BuiltinTypeDeclBuilder &addDefaultHandleConstructor(
Sema &S,
155 if (
Record->isCompleteDefinition())
169 ConstexprSpecKind::Unspecified);
172 lookupBuiltinFunction(AST, S,
"__builtin_hlsl_create_handle");
174 Expr *RCExpr = emitResourceClassExpr(AST, RC);
180 Constructor->getThisType().getTypePtr()->getPointeeType(),
true);
181 This->setValueKind(ExprValueKind::VK_LValue);
203 Constructor->setAccess(AccessSpecifier::AS_public);
204 Record->addDecl(Constructor);
208 BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
209 if (
Record->isCompleteDefinition())
211 addArraySubscriptOperator(
true);
212 addArraySubscriptOperator(
false);
216 BuiltinTypeDeclBuilder &addArraySubscriptOperator(
bool IsConst) {
217 if (
Record->isCompleteDefinition())
219 assert(Fields.count(
"h") > 0 &&
220 "Subscript operator must be added after the handle.");
226 "Not yet supported for void pointer handles.");
250 MethodTy, TSInfo,
SC_None,
false,
false, ConstexprSpecKind::Unspecified,
259 MethodDecl->setParams({IdxParam});
267 MethodDecl->getThisType().getTypePtr()->getPointeeType(),
true);
268 This->setValueKind(ExprValueKind::VK_LValue);
286 MethodDecl->setLexicalDeclContext(Record);
287 MethodDecl->setAccess(AccessSpecifier::AS_public);
288 MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
290 AlwaysInlineAttr::CXX11_clang_always_inline));
291 Record->addDecl(MethodDecl);
296 BuiltinTypeDeclBuilder &startDefinition() {
297 if (
Record->isCompleteDefinition())
299 Record->startDefinition();
303 BuiltinTypeDeclBuilder &completeDefinition() {
304 if (
Record->isCompleteDefinition())
306 assert(
Record->isBeingDefined() &&
307 "Definition must be started before completing it.");
309 Record->completeDefinition();
313 TemplateParameterListBuilder addTemplateArgumentList();
316struct TemplateParameterListBuilder {
317 BuiltinTypeDeclBuilder &Builder;
321 TemplateParameterListBuilder(BuiltinTypeDeclBuilder &RB)
322 : Builder(RB), AST(RB.
Record->getASTContext()) {}
324 ~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
326 TemplateParameterListBuilder &
328 if (Builder.Record->isCompleteDefinition())
330 unsigned Position =
static_cast<unsigned>(Params.size());
334 &AST.
Idents.
get(Name, tok::TokenKind::identifier),
false,
336 if (!DefaultValue.isNull())
339 Params.emplace_back(
Decl);
343 BuiltinTypeDeclBuilder &finalizeTemplateArgs() {
353 Builder.Record->setDescribedClassTemplate(Builder.Template);
354 Builder.Template->setImplicit(
true);
355 Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
358 Builder.Template->setPreviousDecl(Builder.PrevTemplate);
359 Builder.Record->getDeclContext()->addDecl(Builder.Template);
362 QualType T = Builder.Template->getInjectedClassNameSpecialization();
369TemplateParameterListBuilder BuiltinTypeDeclBuilder::addTemplateArgumentList() {
370 return TemplateParameterListBuilder(*
this);
397 defineTrivialHLSLTypes();
398 forwardDeclareHLSLTypes();
414void HLSLExternalSemaSource::defineHLSLVectorAlias() {
421 &AST.
Idents.
get(
"element", tok::TokenKind::identifier),
false,
false);
424 TemplateParams.emplace_back(TypeParam);
428 &AST.
Idents.
get(
"element_count", tok::TokenKind::identifier), AST.
IntTy,
433 SizeParam->setDefaultArgument(LiteralExpr);
434 TemplateParams.emplace_back(SizeParam);
453 Record->setImplicit(
true);
457 Record->getIdentifier(), ParamList, Record);
459 Record->setDescribedAliasTemplate(Template);
462 HLSLNamespace->
addDecl(Template);
465void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
466 defineHLSLVectorAlias();
468 ResourceDecl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
"Resource")
471 .completeDefinition()
475void HLSLExternalSemaSource::forwardDeclareHLSLTypes() {
477 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
"RWBuffer")
478 .addTemplateArgumentList()
480 .finalizeTemplateArgs()
482 if (!
Decl->isCompleteDefinition())
485 std::bind(&HLSLExternalSemaSource::completeBufferType,
486 this, std::placeholders::_1)));
490 if (!isa<CXXRecordDecl>(Tag))
492 auto Record = cast<CXXRecordDecl>(Tag);
496 if (
auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record))
497 Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
498 Record = Record->getCanonicalDecl();
499 auto It = Completions.find(Record);
500 if (It == Completions.end())
505void HLSLExternalSemaSource::completeBufferType(
CXXRecordDecl *Record) {
506 BuiltinTypeDeclBuilder(Record)
508 .addDefaultHandleConstructor(*SemaPtr, ResourceClass::UAV)
509 .addArraySubscriptOperators()
510 .annotateResourceClass(HLSLResourceAttr::UAV,
511 HLSLResourceAttr::TypedBuffer)
512 .completeDefinition();
Defines the clang::ASTContext interface.
Defines the clang::attr::Kind enum.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines helper utilities for supporting the HLSL runtime environment.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
unsigned getIntWidth(QualType T) const
DeclarationNameTable DeclarationNames
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const
getInjectedClassNameType - Return the unique reference to the injected class name type for the specif...
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, TemplateTypeParmDecl *ParmDecl=nullptr) const
Retrieve the template type parameter type for a template parameter or parameter pack with the given d...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType UnsignedCharTy
CanQualType UnsignedIntTy
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
QualType getDependentSizedExtVectorType(QualType VectorType, Expr *SizeExpr, SourceLocation AttrLoc) const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
@ AS_Keyword
__ptr16, alignas(...), etc.
A builtin binary operation expression such as "x + y" or "x <= y".
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Represents a C++ constructor within a class.
static CXXConstructorDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited=InheritedConstructor(), Expr *TrailingRequiresClause=nullptr)
static CXXMethodDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, bool isInline, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, Expr *TrailingRequiresClause=nullptr)
Represents a C++ struct/union/class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr, bool DelayTypeCreation=false)
Represents a C++ nested-name-specifier or a global scope specifier.
static CXXStaticCastExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, FPOptionsOverride FPO, SourceLocation L, SourceLocation RParenLoc, SourceRange AngleBrackets)
Represents the this expression in C++.
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Declaration of a class template.
static ClassTemplateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl)
Create a class template node.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
void addDecl(Decl *D)
Add the declaration D into this context.
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
void setHasExternalLexicalStorage(bool ES=true) const
State whether this DeclContext has external storage for declarations lexically in this context.
decl_iterator decls_begin() const
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Decl - This represents one declaration (or definition), e.g.
void setImplicit(bool I=true)
void setLexicalDeclContext(DeclContext *DC)
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
The name of a declaration.
Store information needed for an explicit specifier.
This represents one expression.
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
void setParam(unsigned i, ParmVarDecl *VD)
void CompleteType(TagDecl *Tag) override
Complete an incomplete HLSL builtin type.
void InitializeSema(Sema &S) override
Initialize the semantic source with the Sema instance being used to perform semantic analysis on the ...
~HLSLExternalSemaSource() override
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Represents the results of name lookup.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
This represents a decl that may have a name.
Represent a C++ namespace.
NamespaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this namespace.
static NamespaceDecl * Create(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested)
A C++ nested-name-specifier augmented with source location information.
static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo)
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
A (possibly-)qualified type.
void addConst()
Add the const type qualifier to this QualType.
QualType getCanonicalType() const
static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
Create a return statement.
Sema - This implements semantic analysis and AST building for C.
Scope * getCurScope() const
Retrieve the parser's current scope.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupNamespaceName
Look up a namespace name within a C++ using directive or namespace alias definition,...
@ LookupTagName
Tag name lookup, which finds the names of enums, classes, structs, and unions.
ASTContext & getASTContext() const
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Encodes a location in the source.
A trivial tuple used to represent a source range.
Represents the declaration of a struct/union/class/enum.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
void startDefinition()
Starts the definition of this tag declaration.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
NamedDecl * getParam(unsigned Idx)
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
static TemplateTypeParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc, SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack, bool HasTypeConstraint=false, std::optional< unsigned > NumExpanded=std::nullopt)
static TypeAliasDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
static TypeAliasTemplateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl)
Create a function template node.
A container of type source information.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Represents a C++ using-declaration.
static UsingDirectiveDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation NamespaceLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor)
bool This(InterpState &S, CodePtr OpPC)
bool Call(InterpState &S, CodePtr &PC, const Function *Func)
@ OK_Ordinary
An ordinary object is located at an address in memory.
@ Result
The result type of a method or function.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
Extra information about a function prototype.