clang 22.0.0git
HLSLBuiltinTypeDeclBuilder.cpp
Go to the documentation of this file.
1//===--- HLSLBuiltinTypeDeclBuilder.cpp - HLSL Builtin Type Decl Builder --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Helper classes for creating HLSL builtin class types. Used by external HLSL
10// sema source.
11//
12//===----------------------------------------------------------------------===//
13
16#include "clang/AST/Attr.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/Stmt.h"
21#include "clang/AST/Type.h"
24#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Sema.h"
26#include "clang/Sema/SemaHLSL.h"
27#include "llvm/ADT/SmallVector.h"
28
29using namespace llvm::hlsl;
30
31namespace clang {
32
33namespace hlsl {
34
35namespace {
36
37static FunctionDecl *lookupBuiltinFunction(Sema &S, StringRef Name) {
38 IdentifierInfo &II =
39 S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
40 DeclarationNameInfo NameInfo =
41 DeclarationNameInfo(DeclarationName(&II), SourceLocation());
42 LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
43 // AllowBuiltinCreation is false but LookupDirect will create
44 // the builtin when searching the global scope anyways...
45 S.LookupName(R, S.getCurScope());
46 // FIXME: If the builtin function was user-declared in global scope,
47 // this assert *will* fail. Should this call LookupBuiltin instead?
48 assert(R.isSingleResult() &&
49 "Since this is a builtin it should always resolve!");
50 return cast<FunctionDecl>(R.getFoundDecl());
51}
52
53CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
54 assert(ResTy->isRecordType() && "not a CXXRecord type");
55 for (auto *CD : ResTy->getAsCXXRecordDecl()->ctors())
56 if (CD->isCopyConstructor())
57 return CD;
58 return nullptr;
59}
60} // namespace
61
62// Builder for template arguments of builtin types. Used internally
63// by BuiltinTypeDeclBuilder.
79
80// Builder for methods or constructors of builtin types. Allows creating methods
81// or constructors of builtin types using the builder pattern like this:
82//
83// BuiltinTypeMethodBuilder(RecordBuilder, "MethodName", ReturnType)
84// .addParam("param_name", Type, InOutModifier)
85// .callBuiltin("builtin_name", BuiltinParams...)
86// .finalize();
87//
88// The builder needs to have all of the parameters before it can create
89// a CXXMethodDecl or CXXConstructorDecl. It collects them in addParam calls and
90// when a first method that builds the body is called or when access to 'this`
91// is needed it creates the CXXMethodDecl/CXXConstructorDecl and ParmVarDecls
92// instances. These can then be referenced from the body building methods.
93// Destructor or an explicit call to finalize() will complete the method
94// definition.
95//
96// The callBuiltin helper method accepts constants via `Expr *` or placeholder
97// value arguments to indicate which function arguments to forward to the
98// builtin.
99//
100// If the method that is being built has a non-void return type the
101// finalize() will create a return statement with the value of the last
102// statement (unless the last statement is already a ReturnStmt or the return
103// value is void).
105private:
106 struct Param {
107 const IdentifierInfo &NameII;
108 QualType Ty;
109 HLSLParamModifierAttr::Spelling Modifier;
110 Param(const IdentifierInfo &NameII, QualType Ty,
111 HLSLParamModifierAttr::Spelling Modifier)
112 : NameII(NameII), Ty(Ty), Modifier(Modifier) {}
113 };
114
115 struct LocalVar {
116 StringRef Name;
117 QualType Ty;
118 VarDecl *Decl;
119 LocalVar(StringRef Name, QualType Ty) : Name(Name), Ty(Ty), Decl(nullptr) {}
120 };
121
122 BuiltinTypeDeclBuilder &DeclBuilder;
123 DeclarationName Name;
124 QualType ReturnTy;
125 // method or constructor declaration
126 // (CXXConstructorDecl derives from CXXMethodDecl)
127 CXXMethodDecl *Method;
128 bool IsConst;
129 bool IsCtor;
130 StorageClass SC;
133
134 // Argument placeholders, inspired by std::placeholder. These are the indices
135 // of arguments to forward to `callBuiltin` and other method builder methods.
136 // Additional special values are:
137 // Handle - refers to the resource handle.
138 // LastStmt - refers to the last statement in the method body; referencing
139 // LastStmt will remove the statement from the method body since
140 // it will be linked from the new expression being constructed.
141 enum class PlaceHolder {
142 _0,
143 _1,
144 _2,
145 _3,
146 _4,
147 _5,
148 Handle = 128,
149 CounterHandle,
150 LastStmt
151 };
152
153 Expr *convertPlaceholder(PlaceHolder PH);
154 Expr *convertPlaceholder(LocalVar &Var);
155 Expr *convertPlaceholder(Expr *E) { return E; }
156
157public:
159
161 QualType ReturnTy, bool IsConst = false,
162 bool IsCtor = false, StorageClass SC = SC_None)
163 : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
164 IsConst(IsConst), IsCtor(IsCtor), SC(SC) {}
165
167 QualType ReturnTy, bool IsConst = false,
168 bool IsCtor = false, StorageClass SC = SC_None);
170
172
175
176 BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
177 HLSLParamModifierAttr::Spelling Modifier =
178 HLSLParamModifierAttr::Keyword_in);
180 template <typename... Ts>
181 BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
182 QualType ReturnType, Ts... ArgSpecs);
183 template <typename TLHS, typename TRHS>
184 BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
185 template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
186 template <typename T>
188 template <typename ResourceT, typename ValueT>
189 BuiltinTypeMethodBuilder &setHandleFieldOnResource(ResourceT ResourceRecord,
190 ValueT HandleValue);
191 template <typename T>
194 template <typename ResourceT, typename ValueT>
196 setCounterHandleFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue);
197 template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
202
203private:
204 void createDecl();
205
206 // Makes sure the declaration is created; should be called before any
207 // statement added to the body or when access to 'this' is needed.
208 void ensureCompleteDecl() {
209 if (!Method)
210 createDecl();
211 }
212
213 template <typename ResourceT, typename ValueT>
214 BuiltinTypeMethodBuilder &setFieldOnResource(ResourceT ResourceRecord,
215 ValueT HandleValue,
216 FieldDecl *HandleField);
217};
218
222
225 QualType DefaultValue) {
226 assert(!Builder.Record->isCompleteDefinition() &&
227 "record is already complete");
228 ASTContext &AST = Builder.SemaRef.getASTContext();
229 unsigned Position = static_cast<unsigned>(Params.size());
231 AST, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(),
232 /* TemplateDepth */ 0, Position,
233 &AST.Idents.get(Name, tok::TokenKind::identifier),
234 /* Typename */ true,
235 /* ParameterPack */ false,
236 /* HasTypeConstraint*/ false);
237 if (!DefaultValue.isNull())
238 Decl->setDefaultArgument(AST,
239 Builder.SemaRef.getTrivialTemplateArgumentLoc(
240 DefaultValue, QualType(), SourceLocation()));
241
242 Params.emplace_back(Decl);
243 return *this;
244}
245
246// The concept specialization expression (CSE) constructed in
247// constructConceptSpecializationExpr is constructed so that it
248// matches the CSE that is constructed when parsing the below C++ code:
249//
250// template<typename T>
251// concept is_typed_resource_element_compatible =
252// __builtin_hlsl_typed_resource_element_compatible<T>
253//
254// template<typename element_type> requires
255// is_typed_resource_element_compatible<element_type>
256// struct RWBuffer {
257// element_type Val;
258// };
259//
260// int fn() {
261// RWBuffer<int> Buf;
262// }
263//
264// When dumping the AST and filtering for "RWBuffer", the resulting AST
265// structure is what we're trying to construct below, specifically the
266// CSE portion.
269 Sema &S, ConceptDecl *CD) {
270 ASTContext &Context = S.getASTContext();
271 SourceLocation Loc = Builder.Record->getBeginLoc();
272 DeclarationNameInfo DNI(CD->getDeclName(), Loc);
274 DeclContext *DC = Builder.Record->getDeclContext();
275 TemplateArgumentListInfo TALI(Loc, Loc);
276
277 // Assume that the concept decl has just one template parameter
278 // This parameter should have been added when CD was constructed
279 // in getTypedBufferConceptDecl
280 assert(CD->getTemplateParameters()->size() == 1 &&
281 "unexpected concept decl parameter count");
282 TemplateTypeParmDecl *ConceptTTPD =
283 dyn_cast<TemplateTypeParmDecl>(CD->getTemplateParameters()->getParam(0));
284
285 // this TemplateTypeParmDecl is the template for the resource, and is
286 // used to construct a template argumentthat will be used
287 // to construct the ImplicitConceptSpecializationDecl
289 Context, // AST context
290 Builder.Record->getDeclContext(), // DeclContext
292 /*D=*/0, // Depth in the template parameter list
293 /*P=*/0, // Position in the template parameter list
294 /*Id=*/nullptr, // Identifier for 'T'
295 /*Typename=*/true, // Indicates this is a 'typename' or 'class'
296 /*ParameterPack=*/false, // Not a parameter pack
297 /*HasTypeConstraint=*/false // Has no type constraint
298 );
299
300 T->setDeclContext(DC);
301
302 QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
303
304 // this is the 2nd template argument node, on which
305 // the concept constraint is actually being applied: 'element_type'
306 TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
307
308 QualType CSETType = Context.getTypeDeclType(T);
309
310 // this is the 1st template argument node, which represents
311 // the abstract type that a concept would refer to: 'T'
312 TemplateArgument CSETA = TemplateArgument(CSETType);
313
314 ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
316 Context, Builder.Record->getDeclContext(), Loc, {CSETA});
317
318 // Constraint satisfaction is used to construct the
319 // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
320 // located at the bottom of the sample AST above.
321 const ConstraintSatisfaction CS(CD, {ConceptTA});
324
325 TALI.addArgument(TAL);
326 const ASTTemplateArgumentListInfo *ATALI =
328
329 // In the concept reference, ATALI is what adds the extra
330 // TemplateArgument node underneath CSE
331 ConceptReference *CR =
332 ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
333
335 ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
336
337 return CSE;
338}
339
342 if (Params.empty())
343 return Builder;
344
345 ASTContext &AST = Builder.SemaRef.Context;
347 CD ? constructConceptSpecializationExpr(Builder.SemaRef, CD) : nullptr;
348 auto *ParamList = TemplateParameterList::Create(
351 AST, Builder.Record->getDeclContext(), SourceLocation(),
352 DeclarationName(Builder.Record->getIdentifier()), ParamList,
353 Builder.Record);
354
355 Builder.Record->setDescribedClassTemplate(Builder.Template);
356 Builder.Template->setImplicit(true);
357 Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
358
359 // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
360 // make visible.
361 Builder.Template->setPreviousDecl(Builder.PrevTemplate);
362 Builder.Record->getDeclContext()->addDecl(Builder.Template);
363 Params.clear();
364
365 return Builder;
366}
367
368Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
369 if (PH == PlaceHolder::Handle)
370 return getResourceHandleExpr();
371 if (PH == PlaceHolder::CounterHandle)
373
374 if (PH == PlaceHolder::LastStmt) {
375 assert(!StmtsList.empty() && "no statements in the list");
376 Stmt *LastStmt = StmtsList.pop_back_val();
377 assert(isa<ValueStmt>(LastStmt) && "last statement does not have a value");
378 return cast<ValueStmt>(LastStmt)->getExprStmt();
379 }
380
381 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
382 ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
383 return DeclRefExpr::Create(
384 AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
386 ParamDecl->getType().getNonReferenceType(), VK_PRValue);
387}
388
389Expr *BuiltinTypeMethodBuilder::convertPlaceholder(LocalVar &Var) {
390 VarDecl *VD = Var.Decl;
391 assert(VD && "local variable is not declared");
392 return DeclRefExpr::Create(
393 VD->getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
394 false, DeclarationNameInfo(VD->getDeclName(), SourceLocation()),
395 VD->getType(), VK_LValue);
396}
397
399 StringRef NameStr,
400 QualType ReturnTy,
401 bool IsConst, bool IsCtor,
402 StorageClass SC)
403 : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
404 IsCtor(IsCtor), SC(SC) {
405
406 assert((!NameStr.empty() || IsCtor) && "method needs a name");
407 assert(((IsCtor && !IsConst) || !IsCtor) && "constructor cannot be const");
408
409 ASTContext &AST = DB.SemaRef.getASTContext();
410 if (IsCtor) {
412 AST.getCanonicalTagType(DB.Record));
413 } else {
414 const IdentifierInfo &II =
415 AST.Idents.get(NameStr, tok::TokenKind::identifier);
416 Name = DeclarationName(&II);
417 }
418}
419
422 HLSLParamModifierAttr::Spelling Modifier) {
423 assert(Method == nullptr && "Cannot add param, method already created");
424 const IdentifierInfo &II = DeclBuilder.SemaRef.getASTContext().Idents.get(
425 Name, tok::TokenKind::identifier);
426 Params.emplace_back(II, Ty, Modifier);
427 return *this;
428}
429
430void BuiltinTypeMethodBuilder::createDecl() {
431 assert(Method == nullptr && "Method or constructor is already created");
432
433 // create method or constructor type
434 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
435 SmallVector<QualType> ParamTypes;
436 for (Param &MP : Params)
437 ParamTypes.emplace_back(MP.Ty);
438
440 if (IsConst)
441 ExtInfo.TypeQuals.addConst();
442
443 QualType FuncTy = AST.getFunctionType(ReturnTy, ParamTypes, ExtInfo);
444
445 // create method or constructor decl
446 auto *TSInfo = AST.getTrivialTypeSourceInfo(FuncTy, SourceLocation());
448 if (IsCtor)
450 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo,
451 ExplicitSpecifier(), false, true, false,
453 else
455 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo, SC,
457
458 // create params & set them to the function prototype
460 unsigned CurScopeDepth = DeclBuilder.SemaRef.getCurScope()->getDepth();
461 auto FnProtoLoc =
462 Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
463 for (int I = 0, E = Params.size(); I != E; I++) {
464 Param &MP = Params[I];
466 AST, Method->getDeclContext(), SourceLocation(), SourceLocation(),
467 &MP.NameII, MP.Ty,
469 nullptr);
470 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
471 auto *Mod =
472 HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
473 Parm->addAttr(Mod);
474 }
475 Parm->setScopeInfo(CurScopeDepth, I);
476 ParmDecls.push_back(Parm);
477 FnProtoLoc.setParam(I, Parm);
478 }
479 Method->setParams({ParmDecls});
480}
481
483 ensureCompleteDecl();
484
485 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
487 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
488 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
489 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
490 HandleField->getType(), VK_LValue,
492}
493
495 ensureCompleteDecl();
496
497 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
499 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
500 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
501 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
502 HandleField->getType(), VK_LValue,
504}
505
508 ensureCompleteDecl();
509
510 assert(Var.Decl == nullptr && "local variable is already declared");
511
512 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
513 Var.Decl = VarDecl::Create(
514 AST, Method, SourceLocation(), SourceLocation(),
515 &AST.Idents.get(Var.Name, tok::TokenKind::identifier), Var.Ty,
517 DeclStmt *DS = new (AST) clang::DeclStmt(DeclGroupRef(Var.Decl),
519 StmtsList.push_back(DS);
520 return *this;
521}
522
524 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
526 AST, SourceLocation(), Method->getFunctionObjectParameterType(),
527 /*IsImplicit=*/true);
528 StmtsList.push_back(ThisExpr);
529 return *this;
530}
531
532template <typename... Ts>
535 QualType ReturnType, Ts... ArgSpecs) {
536 ensureCompleteDecl();
537
538 std::array<Expr *, sizeof...(ArgSpecs)> Args{
539 convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
540
541 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
542 FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
544 AST, NestedNameSpecifierLoc(), SourceLocation(), FD, false,
546
547 auto *ImpCast = ImplicitCastExpr::Create(
548 AST, AST.getPointerType(FD->getType()), CK_BuiltinFnToFnPtr, DRE, nullptr,
550
551 if (ReturnType.isNull())
552 ReturnType = FD->getReturnType();
553
554 Expr *Call = CallExpr::Create(AST, ImpCast, Args, ReturnType, VK_PRValue,
556 StmtsList.push_back(Call);
557 return *this;
558}
559
560template <typename TLHS, typename TRHS>
562 Expr *LHSExpr = convertPlaceholder(LHS);
563 Expr *RHSExpr = convertPlaceholder(RHS);
564 Stmt *AssignStmt = BinaryOperator::Create(
565 DeclBuilder.SemaRef.getASTContext(), LHSExpr, RHSExpr, BO_Assign,
568 StmtsList.push_back(AssignStmt);
569 return *this;
570}
571
572template <typename T>
574 Expr *PtrExpr = convertPlaceholder(Ptr);
575 Expr *Deref =
576 UnaryOperator::Create(DeclBuilder.SemaRef.getASTContext(), PtrExpr,
577 UO_Deref, PtrExpr->getType()->getPointeeType(),
579 /*CanOverflow=*/false, FPOptionsOverride());
580 StmtsList.push_back(Deref);
581 return *this;
582}
583
584template <typename T>
587 ensureCompleteDecl();
588
589 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
590
591 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
592 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
594 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
596 StmtsList.push_back(HandleExpr);
597 return *this;
598}
599
600template <typename ResourceT, typename ValueT>
603 ValueT HandleValue) {
604 return setFieldOnResource(ResourceRecord, HandleValue,
605 DeclBuilder.getResourceHandleField());
606}
607
608template <typename ResourceT, typename ValueT>
611 ResourceT ResourceRecord, ValueT HandleValue) {
612 return setFieldOnResource(ResourceRecord, HandleValue,
613 DeclBuilder.getResourceCounterHandleField());
614}
615
616template <typename ResourceT, typename ValueT>
617BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::setFieldOnResource(
618 ResourceT ResourceRecord, ValueT HandleValue, FieldDecl *HandleField) {
619 ensureCompleteDecl();
620
621 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
622 Expr *HandleValueExpr = convertPlaceholder(HandleValue);
623
624 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
625 MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
626 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
628 Stmt *AssignStmt = BinaryOperator::Create(
629 DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr,
630 BO_Assign, HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
632 StmtsList.push_back(AssignStmt);
633 return *this;
634}
635
636template <typename T>
637BuiltinTypeMethodBuilder &
639 ensureCompleteDecl();
640
641 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
642
643 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
644 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
646 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
648 StmtsList.push_back(HandleExpr);
649 return *this;
650}
651
652template <typename T>
654 ensureCompleteDecl();
655
656 Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
657 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
658
659 QualType Ty = ReturnValueExpr->getType();
660 if (Ty->isRecordType()) {
661 // For record types, create a call to copy constructor to ensure proper copy
662 // semantics.
663 auto *ICE =
664 ImplicitCastExpr::Create(AST, Ty.withConst(), CK_NoOp, ReturnValueExpr,
665 nullptr, VK_XValue, FPOptionsOverride());
666 CXXConstructorDecl *CD = lookupCopyConstructor(Ty);
667 assert(CD && "no copy constructor found");
668 ReturnValueExpr = CXXConstructExpr::Create(
669 AST, Ty, SourceLocation(), CD, /*Elidable=*/false, {ICE},
670 /*HadMultipleCandidates=*/false, /*ListInitialization=*/false,
671 /*StdInitListInitialization=*/false,
672 /*ZeroInitListInitialization=*/false, CXXConstructionKind::Complete,
673 SourceRange());
674 }
675 StmtsList.push_back(
676 ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
677 return *this;
678}
679
681 assert(!DeclBuilder.Record->isCompleteDefinition() &&
682 "record is already complete");
683
684 ensureCompleteDecl();
685
686 if (!Method->hasBody()) {
687 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
688 assert((ReturnTy == AST.VoidTy || !StmtsList.empty()) &&
689 "nothing to return from non-void method");
690 if (ReturnTy != AST.VoidTy) {
691 if (Expr *LastExpr = dyn_cast<Expr>(StmtsList.back())) {
692 assert(AST.hasSameUnqualifiedType(LastExpr->getType(),
693 ReturnTy.getNonReferenceType()) &&
694 "Return type of the last statement must match the return type "
695 "of the method");
696 if (!isa<ReturnStmt>(LastExpr)) {
697 StmtsList.pop_back();
698 StmtsList.push_back(
699 ReturnStmt::Create(AST, SourceLocation(), LastExpr, nullptr));
700 }
701 }
702 }
703
704 Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
706 Method->setLexicalDeclContext(DeclBuilder.Record);
707 Method->setAccess(AS_public);
708 Method->addAttr(AlwaysInlineAttr::CreateImplicit(
709 AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
710 DeclBuilder.Record->addDecl(Method);
711 }
712 return DeclBuilder;
713}
714
716 : SemaRef(SemaRef), Record(R) {
717 Record->startDefinition();
718 Template = Record->getDescribedClassTemplate();
719}
720
722 NamespaceDecl *Namespace,
723 StringRef Name)
724 : SemaRef(SemaRef), HLSLNamespace(Namespace) {
725 ASTContext &AST = SemaRef.getASTContext();
726 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
727
729 CXXRecordDecl *PrevDecl = nullptr;
730 if (SemaRef.LookupQualifiedName(Result, HLSLNamespace)) {
731 // Declaration already exists (from precompiled headers)
732 NamedDecl *Found = Result.getFoundDecl();
733 if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
734 PrevDecl = TD->getTemplatedDecl();
735 PrevTemplate = TD;
736 } else
737 PrevDecl = dyn_cast<CXXRecordDecl>(Found);
738 assert(PrevDecl && "Unexpected lookup result type.");
739 }
740
741 if (PrevDecl && PrevDecl->isCompleteDefinition()) {
742 Record = PrevDecl;
743 Template = PrevTemplate;
744 return;
745 }
746
747 Record =
748 CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
749 SourceLocation(), SourceLocation(), &II, PrevDecl);
750 Record->setImplicit(true);
751 Record->setLexicalDeclContext(HLSLNamespace);
752 Record->setHasExternalLexicalStorage();
753
754 // Don't let anyone derive from built-in types.
755 Record->addAttr(
756 FinalAttr::CreateImplicit(AST, SourceRange(), FinalAttr::Keyword_final));
757}
758
760 if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
761 HLSLNamespace->addDecl(Record);
762}
763
767 AccessSpecifier Access) {
768 assert(!Record->isCompleteDefinition() && "record is already complete");
769 assert(Record->isBeingDefined() &&
770 "Definition must be started before adding members!");
771 ASTContext &AST = Record->getASTContext();
772
773 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
774 TypeSourceInfo *MemTySource =
776 auto *Field = FieldDecl::Create(
777 AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
778 nullptr, false, InClassInitStyle::ICIS_NoInit);
779 Field->setAccess(Access);
780 Field->setImplicit(true);
781 for (Attr *A : Attrs) {
782 if (A)
783 Field->addAttr(A);
784 }
785
786 Record->addDecl(Field);
787 Fields[Name] = Field;
788 return *this;
789}
790
792BuiltinTypeDeclBuilder::addBufferHandles(ResourceClass RC, bool IsROV,
793 bool RawBuffer, bool HasCounter,
794 AccessSpecifier Access) {
795 addHandleMember(RC, IsROV, RawBuffer, Access);
796 if (HasCounter)
797 addCounterHandleMember(RC, IsROV, RawBuffer, Access);
798 return *this;
799}
800
801BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
802 ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
803 return addResourceMember("__handle", RC, IsROV, RawBuffer,
804 /*IsCounter=*/false, Access);
805}
806
807BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
808 ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
809 return addResourceMember("__counter_handle", RC, IsROV, RawBuffer,
810 /*IsCounter=*/true, Access);
811}
812
813BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember(
814 StringRef MemberName, ResourceClass RC, bool IsROV, bool RawBuffer,
815 bool IsCounter, AccessSpecifier Access) {
816 assert(!Record->isCompleteDefinition() && "record is already complete");
817
818 ASTContext &Ctx = SemaRef.getASTContext();
819 TypeSourceInfo *ElementTypeInfo =
820 Ctx.getTrivialTypeSourceInfo(getHandleElementType(), SourceLocation());
821
822 // add handle member with resource type attributes
823 QualType AttributedResTy = QualType();
825 HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
826 IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
827 RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
828 ElementTypeInfo
829 ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
830 : nullptr};
831 if (IsCounter)
832 Attrs.push_back(HLSLIsCounterAttr::CreateImplicit(Ctx));
833
834 if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
835 AttributedResTy))
836 addMemberVariable(MemberName, AttributedResTy, {}, Access);
837 return *this;
838}
839
840// Adds default constructor to the resource class:
841// Resource::Resource()
843 assert(!Record->isCompleteDefinition() && "record is already complete");
844
845 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
846 QualType HandleType = getResourceHandleField()->getType();
847 return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
848 false, true)
849 .callBuiltin("__builtin_hlsl_resource_uninitializedhandle", HandleType,
850 PH::Handle)
851 .assign(PH::Handle, PH::LastStmt)
852 .finalize();
853}
854
857 if (HasCounter) {
858 addCreateFromBindingWithImplicitCounter();
859 addCreateFromImplicitBindingWithImplicitCounter();
860 } else {
861 addCreateFromBinding();
862 addCreateFromImplicitBinding();
863 }
864 return *this;
865}
866
867// Adds static method that initializes resource from binding:
868//
869// static Resource<T> __createFromBinding(unsigned registerNo,
870// unsigned spaceNo, int range,
871// unsigned index, const char *name) {
872// Resource<T> tmp;
873// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
874// tmp.__handle, registerNo, spaceNo,
875// range, index, name);
876// return tmp;
877// }
878BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
879 assert(!Record->isCompleteDefinition() && "record is already complete");
880
881 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
882 ASTContext &AST = SemaRef.getASTContext();
883 QualType HandleType = getResourceHandleField()->getType();
885 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
886
887 return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
888 false, false, SC_Static)
889 .addParam("registerNo", AST.UnsignedIntTy)
890 .addParam("spaceNo", AST.UnsignedIntTy)
891 .addParam("range", AST.IntTy)
892 .addParam("index", AST.UnsignedIntTy)
893 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
894 .declareLocalVar(TmpVar)
895 .accessHandleFieldOnResource(TmpVar)
896 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
897 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
898 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
899 .returnValue(TmpVar)
900 .finalize();
901}
902
903// Adds static method that initializes resource from binding:
904//
905// static Resource<T> __createFromImplicitBinding(unsigned orderId,
906// unsigned spaceNo, int range,
907// unsigned index,
908// const char *name) {
909// Resource<T> tmp;
910// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
911// tmp.__handle, spaceNo,
912// range, index, orderId, name);
913// return tmp;
914// }
915BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
916 assert(!Record->isCompleteDefinition() && "record is already complete");
917
918 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
919 ASTContext &AST = SemaRef.getASTContext();
920 QualType HandleType = getResourceHandleField()->getType();
922 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
923
924 return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
925 RecordType, false, false, SC_Static)
926 .addParam("orderId", AST.UnsignedIntTy)
927 .addParam("spaceNo", AST.UnsignedIntTy)
928 .addParam("range", AST.IntTy)
929 .addParam("index", AST.UnsignedIntTy)
930 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
931 .declareLocalVar(TmpVar)
932 .accessHandleFieldOnResource(TmpVar)
933 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
934 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
935 PH::_4)
936 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
937 .returnValue(TmpVar)
938 .finalize();
939}
940
941// Adds static method that initializes resource from binding:
942//
943// static Resource<T>
944// __createFromBindingWithImplicitCounter(unsigned registerNo,
945// unsigned spaceNo, int range,
946// unsigned index, const char *name,
947// unsigned counterOrderId) {
948// Resource<T> tmp;
949// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
950// tmp.__handle, registerNo, spaceNo, range, index, name);
951// tmp.__counter_handle =
952// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
953// tmp.__handle, counterOrderId, spaceNo);
954// return tmp;
955// }
957BuiltinTypeDeclBuilder::addCreateFromBindingWithImplicitCounter() {
958 assert(!Record->isCompleteDefinition() && "record is already complete");
959
960 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
961 ASTContext &AST = SemaRef.getASTContext();
962 QualType HandleType = getResourceHandleField()->getType();
963 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
964 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
965
966 return BuiltinTypeMethodBuilder(*this,
967 "__createFromBindingWithImplicitCounter",
968 RecordType, false, false, SC_Static)
969 .addParam("registerNo", AST.UnsignedIntTy)
970 .addParam("spaceNo", AST.UnsignedIntTy)
971 .addParam("range", AST.IntTy)
972 .addParam("index", AST.UnsignedIntTy)
973 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
974 .addParam("counterOrderId", AST.UnsignedIntTy)
975 .declareLocalVar(TmpVar)
976 .accessHandleFieldOnResource(TmpVar)
977 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
978 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
979 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
980 .accessHandleFieldOnResource(TmpVar)
981 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
982 HandleType, PH::LastStmt, PH::_5, PH::_1)
983 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
984 .returnValue(TmpVar)
985 .finalize();
986}
987
988// Adds static method that initializes resource from binding:
989//
990// static Resource<T>
991// __createFromImplicitBindingWithImplicitCounter(unsigned orderId,
992// unsigned spaceNo, int range,
993// unsigned index,
994// const char *name,
995// unsigned counterOrderId) {
996// Resource<T> tmp;
997// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
998// tmp.__handle, orderId, spaceNo, range, index, name);
999// tmp.__counter_handle =
1000// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1001// tmp.__handle, counterOrderId, spaceNo);
1002// return tmp;
1003// }
1005BuiltinTypeDeclBuilder::addCreateFromImplicitBindingWithImplicitCounter() {
1006 assert(!Record->isCompleteDefinition() && "record is already complete");
1007
1008 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1009 ASTContext &AST = SemaRef.getASTContext();
1010 QualType HandleType = getResourceHandleField()->getType();
1011 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1012 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1013
1015 *this, "__createFromImplicitBindingWithImplicitCounter",
1016 RecordType, false, false, SC_Static)
1017 .addParam("orderId", AST.UnsignedIntTy)
1018 .addParam("spaceNo", AST.UnsignedIntTy)
1019 .addParam("range", AST.IntTy)
1020 .addParam("index", AST.UnsignedIntTy)
1021 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1022 .addParam("counterOrderId", AST.UnsignedIntTy)
1023 .declareLocalVar(TmpVar)
1024 .accessHandleFieldOnResource(TmpVar)
1025 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1026 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1027 PH::_4)
1028 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1029 .accessHandleFieldOnResource(TmpVar)
1030 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1031 HandleType, PH::LastStmt, PH::_5, PH::_1)
1032 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1033 .returnValue(TmpVar)
1034 .finalize();
1035}
1036
1038 assert(!Record->isCompleteDefinition() && "record is already complete");
1039
1040 ASTContext &AST = SemaRef.getASTContext();
1041 QualType RecordType = AST.getCanonicalTagType(Record);
1042 QualType ConstRecordType = RecordType.withConst();
1043 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1044
1045 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1046
1047 BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy,
1048 /*IsConst=*/false, /*IsCtor=*/true);
1049 MMB.addParam("other", ConstRecordRefType)
1051 .assign(PH::Handle, PH::LastStmt);
1052
1053 if (getResourceCounterHandleField())
1054 MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
1055 PH::LastStmt);
1056
1057 return MMB.finalize();
1058}
1059
1061 assert(!Record->isCompleteDefinition() && "record is already complete");
1062
1063 ASTContext &AST = SemaRef.getASTContext();
1064 QualType RecordType = AST.getCanonicalTagType(Record);
1065 QualType ConstRecordType = RecordType.withConst();
1066 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1067 QualType RecordRefType = AST.getLValueReferenceType(RecordType);
1068
1069 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1071 BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType);
1072 MMB.addParam("other", ConstRecordRefType)
1074 .assign(PH::Handle, PH::LastStmt);
1075
1076 if (getResourceCounterHandleField())
1077 MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
1078 PH::LastStmt);
1079
1080 return MMB.returnThis().finalize();
1081}
1082
1084 ASTContext &AST = Record->getASTContext();
1085 DeclarationName Subscript =
1086 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1087
1088 addHandleAccessFunction(Subscript, /*IsConst=*/true, /*IsRef=*/true);
1089 if (getResourceAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV)
1090 addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true);
1091
1092 return *this;
1093}
1094
1096 assert(!Record->isCompleteDefinition() && "record is already complete");
1097
1098 ASTContext &AST = Record->getASTContext();
1099 IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
1100 DeclarationName Load(&II);
1101 // TODO: We also need versions with status for CheckAccessFullyMapped.
1102 addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false);
1103
1104 return *this;
1105}
1106
1107FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
1108 auto I = Fields.find("__handle");
1109 assert(I != Fields.end() &&
1110 I->second->getType()->isHLSLAttributedResourceType() &&
1111 "record does not have resource handle field");
1112 return I->second;
1113}
1114
1115FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField() const {
1116 auto I = Fields.find("__counter_handle");
1117 if (I == Fields.end() ||
1118 !I->second->getType()->isHLSLAttributedResourceType())
1119 return nullptr;
1120 return I->second;
1121}
1122
1123QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
1124 assert(Template && "record it not a template");
1125 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
1126 Template->getTemplateParameters()->getParam(0))) {
1127 return QualType(TTD->getTypeForDecl(), 0);
1128 }
1129 return QualType();
1130}
1131
1132QualType BuiltinTypeDeclBuilder::getHandleElementType() {
1133 if (Template)
1134 return getFirstTemplateTypeParam();
1135 // TODO: Should we default to VoidTy? Using `i8` is arguably ambiguous.
1136 return SemaRef.getASTContext().Char8Ty;
1137}
1138
1139HLSLAttributedResourceType::Attributes
1140BuiltinTypeDeclBuilder::getResourceAttrs() const {
1141 QualType HandleType = getResourceHandleField()->getType();
1142 return cast<HLSLAttributedResourceType>(HandleType)->getAttrs();
1143}
1144
1146 assert(!Record->isCompleteDefinition() && "record is already complete");
1147 assert(Record->isBeingDefined() &&
1148 "Definition must be started before completing it.");
1149
1150 Record->completeDefinition();
1151 return *this;
1152}
1153
1154Expr *BuiltinTypeDeclBuilder::getConstantIntExpr(int value) {
1155 ASTContext &AST = SemaRef.getASTContext();
1157 AST, llvm::APInt(AST.getTypeSize(AST.IntTy), value, true), AST.IntTy,
1158 SourceLocation());
1159}
1160
1163 ConceptDecl *CD = nullptr) {
1164 if (Record->isCompleteDefinition()) {
1165 assert(Template && "existing record it not a template");
1166 assert(Template->getTemplateParameters()->size() == Names.size() &&
1167 "template param count mismatch");
1168 return *this;
1169 }
1170
1172 for (StringRef Name : Names)
1173 Builder.addTypeParameter(Name);
1174 return Builder.finalizeTemplateArgs(CD);
1175}
1176
1178 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1179 return BuiltinTypeMethodBuilder(*this, "IncrementCounter",
1180 SemaRef.getASTContext().UnsignedIntTy)
1181 .callBuiltin("__builtin_hlsl_buffer_update_counter", QualType(),
1182 PH::CounterHandle, getConstantIntExpr(1))
1183 .finalize();
1184}
1185
1187 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1188 return BuiltinTypeMethodBuilder(*this, "DecrementCounter",
1189 SemaRef.getASTContext().UnsignedIntTy)
1190 .callBuiltin("__builtin_hlsl_buffer_update_counter", QualType(),
1191 PH::CounterHandle, getConstantIntExpr(-1))
1192 .finalize();
1193}
1194
1197 bool IsConst, bool IsRef) {
1198 assert(!Record->isCompleteDefinition() && "record is already complete");
1199 ASTContext &AST = SemaRef.getASTContext();
1200 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1201
1202 QualType ElemTy = getHandleElementType();
1203 QualType AddrSpaceElemTy =
1205 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
1206 QualType ReturnTy;
1207
1208 if (IsRef) {
1209 ReturnTy = AddrSpaceElemTy;
1210 if (IsConst)
1211 ReturnTy.addConst();
1212 ReturnTy = AST.getLValueReferenceType(ReturnTy);
1213 } else {
1214 ReturnTy = ElemTy;
1215 if (IsConst)
1216 ReturnTy.addConst();
1217 }
1218
1219 return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, IsConst)
1220 .addParam("Index", AST.UnsignedIntTy)
1221 .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
1222 PH::_0)
1223 .dereference(PH::LastStmt)
1224 .finalize();
1225}
1226
1228 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1229 ASTContext &AST = SemaRef.getASTContext();
1230 QualType ElemTy = getHandleElementType();
1231 QualType AddrSpaceElemTy =
1233 return BuiltinTypeMethodBuilder(*this, "Append", AST.VoidTy)
1234 .addParam("value", ElemTy)
1235 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
1236 PH::CounterHandle, getConstantIntExpr(1))
1237 .callBuiltin("__builtin_hlsl_resource_getpointer",
1238 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
1239 PH::LastStmt)
1240 .dereference(PH::LastStmt)
1241 .assign(PH::LastStmt, PH::_0)
1242 .finalize();
1243}
1244
1246 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1247 ASTContext &AST = SemaRef.getASTContext();
1248 QualType ElemTy = getHandleElementType();
1249 QualType AddrSpaceElemTy =
1251 return BuiltinTypeMethodBuilder(*this, "Consume", ElemTy)
1252 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
1253 PH::CounterHandle, getConstantIntExpr(-1))
1254 .callBuiltin("__builtin_hlsl_resource_getpointer",
1255 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
1256 PH::LastStmt)
1257 .dereference(PH::LastStmt)
1258 .finalize();
1259}
1260
1261} // namespace hlsl
1262} // namespace clang
Defines the clang::ASTContext interface.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
llvm::MachO::Record Record
Definition MachO.h:31
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
if(__y==0) return __x
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType CharTy
CanQualType IntTy
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
CanQualType UnsignedIntTy
a trap message and trap category.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
DeclarationNameTable DeclarationNames
Definition ASTContext.h:776
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
IdentifierTable & Idents
Definition ASTContext.h:772
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType CharTy
CanQualType IntTy
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType BuiltinFnTy
CanQualType VoidTy
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 getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
Attr - This represents one attribute.
Definition Attr.h:44
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Definition Expr.cpp:4979
static CXXConstructExpr * Create(const ASTContext &Ctx, QualType Ty, SourceLocation Loc, CXXConstructorDecl *Ctor, bool Elidable, ArrayRef< Expr * > Args, bool HadMultipleCandidates, bool ListInitialization, bool StdInitListInitialization, bool ZeroInitialization, CXXConstructionKind ConstructKind, SourceRange ParenOrBraceRange)
Create a C++ construction expression.
Definition ExprCXX.cpp:1180
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
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(), const AssociatedConstraint &TrailingRequiresClause={})
Definition DeclCXX.cpp:2968
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
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, const AssociatedConstraint &TrailingRequiresClause={})
Definition DeclCXX.cpp:2488
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
Definition DeclCXX.cpp:132
Represents the this expression in C++.
Definition ExprCXX.h:1155
static CXXThisExpr * Create(const ASTContext &Ctx, SourceLocation L, QualType Ty, bool IsImplicit)
Definition ExprCXX.cpp:1585
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.
Definition Expr.cpp:1513
QualType withConst() const
Retrieves a version of this type with const applied.
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)
Definition Stmt.cpp:390
Declaration of a C++20 concept.
A reference to a concept and its template args, as it appears in the code.
Definition ASTConcept.h:130
static ConceptReference * Create(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten)
Represents the specialization of a concept - evaluates to a prvalue of type bool.
static ConceptSpecializationExpr * Create(const ASTContext &C, ConceptReference *ConceptRef, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction)
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:47
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
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)
Definition Expr.cpp:484
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1611
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void addAttr(Attr *A)
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op)
Get the name of the overloadable C++ operator corresponding to Op.
DeclarationName getCXXConstructorName(CanQualType Ty)
Returns the name of a C++ constructor for the given Type.
The name of a declaration.
Store information needed for an explicit specifier.
Definition DeclCXX.h:1924
This represents one expression.
Definition Expr.h:112
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Definition Decl.h:3160
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Definition Decl.cpp:4688
Represents a function declaration or definition.
Definition Decl.h:2000
QualType getReturnType() const
Definition Decl.h:2845
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2211
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 ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2068
static ImplicitConceptSpecializationDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation SL, ArrayRef< TemplateArgument > ConvertedArgs)
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'.
Definition Expr.cpp:971
Represents the results of name lookup.
Definition Lookup.h:147
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3298
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.
Definition Expr.h:3359
This represents a decl that may have a name.
Definition Decl.h:274
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
Represent a C++ namespace.
Definition Decl.h:592
A C++ nested-name-specifier augmented with source location information.
Represents a parameter to a function.
Definition Decl.h:1790
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
Definition Decl.h:1823
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition Decl.cpp:2946
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType withConst() const
Definition TypeBase.h:1159
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1156
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8475
static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
Create a return statement.
Definition Stmt.cpp:1248
unsigned getDepth() const
Returns the depth of this scope. The translation-unit has scope depth 0.
Definition Scope.h:339
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, NamedDecl *TemplateParam=nullptr)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1120
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9291
@ LookupTagName
Tag name lookup, which finds the names of enums, classes, structs, and unions.
Definition Sema.h:9294
ASTContext & getASTContext() const
Definition Sema.h:925
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition Stmt.h:85
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3812
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
Location wrapper for a TemplateArgument.
Represents a template argument.
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)
Declaration of a template type parameter.
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, UnsignedOrNone NumExpanded=std::nullopt)
A container of type source information.
Definition TypeBase.h:8261
The base class of the type hierarchy.
Definition TypeBase.h:1833
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool isRecordType() const
Definition TypeBase.h:8654
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Definition Expr.cpp:5036
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2151
BuiltinTypeDeclBuilder(Sema &SemaRef, CXXRecordDecl *R)
BuiltinTypeDeclBuilder & addSimpleTemplateParams(ArrayRef< StringRef > Names, ConceptDecl *CD)
BuiltinTypeDeclBuilder & addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef< Attr * > Attrs, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addHandleAccessFunction(DeclarationName &Name, bool IsConst, bool IsRef)
BuiltinTypeDeclBuilder & addBufferHandles(ResourceClass RC, bool IsROV, bool RawBuffer, bool HasCounter, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addStaticInitializationFunctions(bool HasCounter)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ ICIS_NoInit
No in-class initializer.
Definition Specifiers.h:272
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition Specifiers.h:123
@ AS_public
Definition Specifiers.h:124
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
Definition Specifiers.h:248
@ SC_Static
Definition Specifiers.h:252
@ SC_None
Definition Specifiers.h:250
@ Result
The result type of a method or function.
Definition TypeBase.h:905
const FunctionProtoType * T
@ Template
We are parsing a template declaration.
Definition Parser.h:81
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
Definition Specifiers.h:144
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:139
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Other
Other implicit parameter.
Definition Decl.h:1746
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
static const ASTTemplateArgumentListInfo * Create(const ASTContext &C, const TemplateArgumentListInfo &List)
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
Extra information about a function prototype.
Definition TypeBase.h:5351
BuiltinTypeMethodBuilder & addParam(StringRef Name, QualType Ty, HLSLParamModifierAttr::Spelling Modifier=HLSLParamModifierAttr::Keyword_in)
BuiltinTypeMethodBuilder & accessHandleFieldOnResource(T ResourceRecord)
BuiltinTypeMethodBuilder & operator=(const BuiltinTypeMethodBuilder &Other)=delete
BuiltinTypeMethodBuilder & callBuiltin(StringRef BuiltinName, QualType ReturnType, Ts... ArgSpecs)
BuiltinTypeMethodBuilder & dereference(T Ptr)
BuiltinTypeMethodBuilder & declareLocalVar(LocalVar &Var)
BuiltinTypeMethodBuilder & assign(TLHS LHS, TRHS RHS)
BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other)=delete
BuiltinTypeMethodBuilder & accessCounterHandleFieldOnResource(T ResourceRecord)
BuiltinTypeMethodBuilder & setCounterHandleFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue)
BuiltinTypeMethodBuilder & setHandleFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue)
BuiltinTypeMethodBuilder & returnValue(T ReturnValue)
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, DeclarationName &Name, QualType ReturnTy, bool IsConst=false, bool IsCtor=false, StorageClass SC=SC_None)
TemplateParameterListBuilder & addTypeParameter(StringRef Name, QualType DefaultValue=QualType())
BuiltinTypeDeclBuilder & finalizeTemplateArgs(ConceptDecl *CD=nullptr)
ConceptSpecializationExpr * constructConceptSpecializationExpr(Sema &S, ConceptDecl *CD)