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();
74 FinalAttr::Keyword_final));
77 ~BuiltinTypeDeclBuilder() {
78 if (HLSLNamespace && !Template &&
Record->getDeclContext() == HLSLNamespace)
82 BuiltinTypeDeclBuilder &
85 if (
Record->isCompleteDefinition())
87 assert(
Record->isBeingDefined() &&
88 "Definition must be started before adding members!");
96 nullptr,
false, InClassInitStyle::ICIS_NoInit);
97 Field->setAccess(Access);
98 Field->setImplicit(
true);
100 Fields[Name] =
Field;
104 BuiltinTypeDeclBuilder &
105 addHandleMember(
AccessSpecifier Access = AccessSpecifier::AS_private) {
106 if (
Record->isCompleteDefinition())
110 if (
const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
112 Ty =
Record->getASTContext().getPointerType(
113 QualType(TTD->getTypeForDecl(), 0));
115 return addMemberVariable(
"h", Ty, Access);
118 BuiltinTypeDeclBuilder &
119 annotateResourceClass(HLSLResourceAttr::ResourceClass RC,
120 HLSLResourceAttr::ResourceKind RK) {
121 if (
Record->isCompleteDefinition())
124 HLSLResourceAttr::CreateImplicit(
Record->getASTContext(), RC, RK));
136 assert(R.isSingleResult() &&
137 "Since this is a builtin it should always resolve!");
138 auto *VD = cast<ValueDecl>(R.getFoundDecl());
144 static Expr *emitResourceClassExpr(
ASTContext &AST, ResourceClass RC) {
148 static_cast<uint8_t
>(RC)),
152 BuiltinTypeDeclBuilder &addDefaultHandleConstructor(
Sema &S,
154 if (
Record->isCompleteDefinition())
168 ConstexprSpecKind::Unspecified);
171 lookupBuiltinFunction(AST, S,
"__builtin_hlsl_create_handle");
173 Expr *RCExpr = emitResourceClassExpr(AST, RC);
201 Constructor->setAccess(AccessSpecifier::AS_public);
202 Record->addDecl(Constructor);
206 BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
207 if (
Record->isCompleteDefinition())
209 addArraySubscriptOperator(
true);
210 addArraySubscriptOperator(
false);
214 BuiltinTypeDeclBuilder &addArraySubscriptOperator(
bool IsConst) {
215 if (
Record->isCompleteDefinition())
217 assert(Fields.count(
"h") > 0 &&
218 "Subscript operator must be added after the handle.");
224 "Not yet supported for void pointer handles.");
248 MethodTy, TSInfo,
SC_None,
false,
false, ConstexprSpecKind::Unspecified,
257 MethodDecl->setParams({IdxParam});
265 MethodDecl->getThisObjectType(),
true);
283 MethodDecl->setLexicalDeclContext(Record);
284 MethodDecl->setAccess(AccessSpecifier::AS_public);
285 MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
286 AST,
SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
287 Record->addDecl(MethodDecl);
292 BuiltinTypeDeclBuilder &startDefinition() {
293 if (
Record->isCompleteDefinition())
295 Record->startDefinition();
299 BuiltinTypeDeclBuilder &completeDefinition() {
300 if (
Record->isCompleteDefinition())
302 assert(
Record->isBeingDefined() &&
303 "Definition must be started before completing it.");
305 Record->completeDefinition();
309 TemplateParameterListBuilder addTemplateArgumentList();
312struct TemplateParameterListBuilder {
313 BuiltinTypeDeclBuilder &Builder;
317 TemplateParameterListBuilder(BuiltinTypeDeclBuilder &RB)
318 : Builder(RB), AST(RB.
Record->getASTContext()) {}
320 ~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
322 TemplateParameterListBuilder &
324 if (Builder.Record->isCompleteDefinition())
326 unsigned Position =
static_cast<unsigned>(Params.size());
330 &AST.
Idents.
get(Name, tok::TokenKind::identifier),
false,
332 if (!DefaultValue.isNull())
335 Params.emplace_back(
Decl);
339 BuiltinTypeDeclBuilder &finalizeTemplateArgs() {
349 Builder.Record->setDescribedClassTemplate(Builder.Template);
350 Builder.Template->setImplicit(
true);
351 Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
354 Builder.Template->setPreviousDecl(Builder.PrevTemplate);
355 Builder.Record->getDeclContext()->addDecl(Builder.Template);
358 QualType T = Builder.Template->getInjectedClassNameSpecialization();
365TemplateParameterListBuilder BuiltinTypeDeclBuilder::addTemplateArgumentList() {
366 return TemplateParameterListBuilder(*
this);
393 defineTrivialHLSLTypes();
394 forwardDeclareHLSLTypes();
410void HLSLExternalSemaSource::defineHLSLVectorAlias() {
417 &AST.
Idents.
get(
"element", tok::TokenKind::identifier),
false,
false);
420 TemplateParams.emplace_back(TypeParam);
424 &AST.
Idents.
get(
"element_count", tok::TokenKind::identifier), AST.
IntTy,
429 SizeParam->setDefaultArgument(LiteralExpr);
430 TemplateParams.emplace_back(SizeParam);
449 Record->setImplicit(
true);
453 Record->getIdentifier(), ParamList, Record);
455 Record->setDescribedAliasTemplate(Template);
458 HLSLNamespace->
addDecl(Template);
461void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
462 defineHLSLVectorAlias();
464 ResourceDecl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
"Resource")
467 .completeDefinition()
471void HLSLExternalSemaSource::forwardDeclareHLSLTypes() {
473 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
"RWBuffer")
474 .addTemplateArgumentList()
476 .finalizeTemplateArgs()
478 if (!
Decl->isCompleteDefinition())
481 std::bind(&HLSLExternalSemaSource::completeBufferType,
482 this, std::placeholders::_1)));
486 if (!isa<CXXRecordDecl>(Tag))
488 auto Record = cast<CXXRecordDecl>(Tag);
492 if (
auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record))
493 Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
494 Record = Record->getCanonicalDecl();
495 auto It = Completions.find(Record);
496 if (It == Completions.end())
501void HLSLExternalSemaSource::completeBufferType(
CXXRecordDecl *Record) {
502 BuiltinTypeDeclBuilder(Record)
504 .addDefaultHandleConstructor(*SemaPtr, ResourceClass::UAV)
505 .addArraySubscriptOperators()
506 .annotateResourceClass(HLSLResourceAttr::UAV,
507 HLSLResourceAttr::TypedBuffer)
508 .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.
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 CXXThisExpr * Create(const ASTContext &Ctx, SourceLocation L, QualType Ty, bool IsImplicit)
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 Call(InterpState &S, CodePtr OpPC, const Function *Func)
bool This(InterpState &S, CodePtr OpPC)
@ 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 correspon...
Extra information about a function prototype.