clang 23.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"
20#include "clang/AST/Expr.h"
22#include "clang/AST/Stmt.h"
23#include "clang/AST/Type.h"
26#include "clang/Sema/Lookup.h"
27#include "clang/Sema/Sema.h"
28#include "clang/Sema/SemaHLSL.h"
29#include "llvm/ADT/SmallVector.h"
30
31using namespace llvm::hlsl;
32
33namespace clang {
34
35namespace hlsl {
36
37namespace {
38
39static FunctionDecl *lookupBuiltinFunction(Sema &S, StringRef Name) {
40 IdentifierInfo &II =
41 S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
42 DeclarationNameInfo NameInfo =
43 DeclarationNameInfo(DeclarationName(&II), SourceLocation());
44 LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
45 // AllowBuiltinCreation is false but LookupDirect will create
46 // the builtin when searching the global scope anyways...
47 S.LookupName(R, S.getCurScope());
48 // FIXME: If the builtin function was user-declared in global scope,
49 // this assert *will* fail. Should this call LookupBuiltin instead?
50 assert(R.isSingleResult() &&
51 "Since this is a builtin it should always resolve!");
52 return cast<FunctionDecl>(R.getFoundDecl());
53}
54
55static QualType lookupBuiltinType(Sema &S, StringRef Name, DeclContext *DC) {
56 IdentifierInfo &II =
57 S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
58 LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
59 S.LookupQualifiedName(Result, DC);
60 assert(!Result.empty() && "Builtin type not found");
61 QualType Ty =
62 S.getASTContext().getTypeDeclType(Result.getAsSingle<TypeDecl>());
63 S.RequireCompleteType(SourceLocation(), Ty,
64 diag::err_tentative_def_incomplete_type);
65 return Ty;
66}
67
68CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
69 assert(ResTy->isRecordType() && "not a CXXRecord type");
70 for (auto *CD : ResTy->getAsCXXRecordDecl()->ctors())
71 if (CD->isCopyConstructor())
72 return CD;
73 return nullptr;
74}
75
77convertParamModifierToParamABI(HLSLParamModifierAttr::Spelling Modifier) {
78 assert(Modifier != HLSLParamModifierAttr::Spelling::Keyword_in &&
79 "HLSL 'in' parameters modifier cannot be converted to ParameterABI");
80 switch (Modifier) {
81 case HLSLParamModifierAttr::Spelling::Keyword_out:
83 case HLSLParamModifierAttr::Spelling::Keyword_inout:
85 default:
86 llvm_unreachable("Invalid HLSL parameter modifier");
87 }
88}
89
90QualType getInoutParameterType(ASTContext &AST, QualType Ty) {
91 assert(!Ty->isReferenceType() &&
92 "Pointer and reference types cannot be inout or out parameters");
93 Ty = AST.getLValueReferenceType(Ty);
94 Ty.addRestrict();
95 return Ty;
96}
97
98} // namespace
99
100// Builder for template arguments of builtin types. Used internally
101// by BuiltinTypeDeclBuilder.
117
118// Builder for methods or constructors of builtin types. Allows creating methods
119// or constructors of builtin types using the builder pattern like this:
120//
121// BuiltinTypeMethodBuilder(RecordBuilder, "MethodName", ReturnType)
122// .addParam("param_name", Type, InOutModifier)
123// .callBuiltin("builtin_name", BuiltinParams...)
124// .finalize();
125//
126// The builder needs to have all of the parameters before it can create
127// a CXXMethodDecl or CXXConstructorDecl. It collects them in addParam calls and
128// when a first method that builds the body is called or when access to 'this`
129// is needed it creates the CXXMethodDecl/CXXConstructorDecl and ParmVarDecls
130// instances. These can then be referenced from the body building methods.
131// Destructor or an explicit call to finalize() will complete the method
132// definition.
133//
134// The callBuiltin helper method accepts constants via `Expr *` or placeholder
135// value arguments to indicate which function arguments to forward to the
136// builtin.
137//
138// If the method that is being built has a non-void return type the
139// finalize() will create a return statement with the value of the last
140// statement (unless the last statement is already a ReturnStmt or the return
141// value is void).
143private:
144 struct Param {
145 const IdentifierInfo &NameII;
146 QualType Ty;
147 HLSLParamModifierAttr::Spelling Modifier;
148 Param(const IdentifierInfo &NameII, QualType Ty,
149 HLSLParamModifierAttr::Spelling Modifier)
150 : NameII(NameII), Ty(Ty), Modifier(Modifier) {}
151 };
152
153 struct LocalVar {
154 StringRef Name;
155 QualType Ty;
156 VarDecl *Decl;
157 LocalVar(StringRef Name, QualType Ty) : Name(Name), Ty(Ty), Decl(nullptr) {}
158 };
159
160 BuiltinTypeDeclBuilder &DeclBuilder;
161 DeclarationName Name;
162 QualType ReturnTy;
163 // method or constructor declaration
164 // (CXXConstructorDecl derives from CXXMethodDecl)
165 CXXMethodDecl *Method;
166 bool IsConst;
167 bool IsCtor;
168 StorageClass SC;
171 TemplateParameterList *TemplateParams = nullptr;
172 llvm::SmallVector<NamedDecl *> TemplateParamDecls;
173
174 // Argument placeholders, inspired by std::placeholder. These are the indices
175 // of arguments to forward to `callBuiltin` and other method builder methods.
176 // Additional special values are:
177 // Handle - refers to the resource handle.
178 // LastStmt - refers to the last statement in the method body; referencing
179 // LastStmt will remove the statement from the method body since
180 // it will be linked from the new expression being constructed.
181 enum class PlaceHolder {
182 _0,
183 _1,
184 _2,
185 _3,
186 _4,
187 _5,
188 Handle = 128,
189 CounterHandle,
190 LastStmt
191 };
192
193 Expr *convertPlaceholder(PlaceHolder PH);
194 Expr *convertPlaceholder(LocalVar &Var);
195 Expr *convertPlaceholder(Expr *E) { return E; }
196 // Converts a QualType to an Expr that carries type information to builtins.
197 Expr *convertPlaceholder(QualType Ty);
198
199public:
201
203 QualType ReturnTy, bool IsConst = false,
204 bool IsCtor = false, StorageClass SC = SC_None)
205 : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
206 IsConst(IsConst), IsCtor(IsCtor), SC(SC) {}
207
209 QualType ReturnTy, bool IsConst = false,
210 bool IsCtor = false, StorageClass SC = SC_None);
212
214
217
218 BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
219 HLSLParamModifierAttr::Spelling Modifier =
220 HLSLParamModifierAttr::Keyword_in);
221 QualType addTemplateTypeParam(StringRef Name);
223 template <typename... Ts>
224 BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
225 QualType ReturnType, Ts &&...ArgSpecs);
226 template <typename TLHS, typename TRHS>
227 BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
228 template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
229
230 template <typename T>
232 template <typename ResourceT, typename ValueT>
233 BuiltinTypeMethodBuilder &setHandleFieldOnResource(ResourceT ResourceRecord,
234 ValueT HandleValue);
235 template <typename T>
237 accessCounterHandleFieldOnResource(T ResourceRecord);
238 template <typename ResourceT, typename ValueT>
240 setCounterHandleFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue);
241 template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
246
247private:
248 void createDecl();
249
250 // Makes sure the declaration is created; should be called before any
251 // statement added to the body or when access to 'this' is needed.
252 void ensureCompleteDecl() {
253 if (!Method)
254 createDecl();
255 }
256
257 template <typename ResourceT, typename ValueT>
258 BuiltinTypeMethodBuilder &setFieldOnResource(ResourceT ResourceRecord,
259 ValueT HandleValue,
260 FieldDecl *HandleField);
261};
262
266
269 QualType DefaultValue) {
270 assert(!Builder.Record->isCompleteDefinition() &&
271 "record is already complete");
272 ASTContext &AST = Builder.SemaRef.getASTContext();
273 unsigned Position = static_cast<unsigned>(Params.size());
275 AST, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(),
276 /* TemplateDepth */ 0, Position,
277 &AST.Idents.get(Name, tok::TokenKind::identifier),
278 /* Typename */ true,
279 /* ParameterPack */ false,
280 /* HasTypeConstraint*/ false);
281 if (!DefaultValue.isNull())
282 Decl->setDefaultArgument(AST,
283 Builder.SemaRef.getTrivialTemplateArgumentLoc(
284 DefaultValue, QualType(), SourceLocation()));
285
286 Params.emplace_back(Decl);
287 return *this;
288}
289
290// The concept specialization expression (CSE) constructed in
291// constructConceptSpecializationExpr is constructed so that it
292// matches the CSE that is constructed when parsing the below C++ code:
293//
294// template<typename T>
295// concept is_typed_resource_element_compatible =
296// __builtin_hlsl_typed_resource_element_compatible<T>
297//
298// template<typename element_type> requires
299// is_typed_resource_element_compatible<element_type>
300// struct RWBuffer {
301// element_type Val;
302// };
303//
304// int fn() {
305// RWBuffer<int> Buf;
306// }
307//
308// When dumping the AST and filtering for "RWBuffer", the resulting AST
309// structure is what we're trying to construct below, specifically the
310// CSE portion.
313 Sema &S, ConceptDecl *CD) {
314 ASTContext &Context = S.getASTContext();
315 SourceLocation Loc = Builder.Record->getBeginLoc();
316 DeclarationNameInfo DNI(CD->getDeclName(), Loc);
318 DeclContext *DC = Builder.Record->getDeclContext();
319 TemplateArgumentListInfo TALI(Loc, Loc);
320
321 // Assume that the concept decl has just one template parameter
322 // This parameter should have been added when CD was constructed
323 // in getTypedBufferConceptDecl
324 assert(CD->getTemplateParameters()->size() == 1 &&
325 "unexpected concept decl parameter count");
326 TemplateTypeParmDecl *ConceptTTPD =
327 dyn_cast<TemplateTypeParmDecl>(CD->getTemplateParameters()->getParam(0));
328
329 // this TemplateTypeParmDecl is the template for the resource, and is
330 // used to construct a template argumentthat will be used
331 // to construct the ImplicitConceptSpecializationDecl
333 Context, // AST context
334 Builder.Record->getDeclContext(), // DeclContext
336 /*D=*/0, // Depth in the template parameter list
337 /*P=*/0, // Position in the template parameter list
338 /*Id=*/nullptr, // Identifier for 'T'
339 /*Typename=*/true, // Indicates this is a 'typename' or 'class'
340 /*ParameterPack=*/false, // Not a parameter pack
341 /*HasTypeConstraint=*/false // Has no type constraint
342 );
343
344 T->setDeclContext(DC);
345
346 QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
347
348 // this is the 2nd template argument node, on which
349 // the concept constraint is actually being applied: 'element_type'
350 TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
351
352 QualType CSETType = Context.getTypeDeclType(T);
353
354 // this is the 1st template argument node, which represents
355 // the abstract type that a concept would refer to: 'T'
356 TemplateArgument CSETA = TemplateArgument(CSETType);
357
358 ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
360 Context, Builder.Record->getDeclContext(), Loc, {CSETA});
361
362 // Constraint satisfaction is used to construct the
363 // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
364 // located at the bottom of the sample AST above.
365 const ConstraintSatisfaction CS(CD, {ConceptTA});
368
369 TALI.addArgument(TAL);
370 const ASTTemplateArgumentListInfo *ATALI =
372
373 // In the concept reference, ATALI is what adds the extra
374 // TemplateArgument node underneath CSE
375 ConceptReference *CR =
376 ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
377
379 ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
380
381 return CSE;
382}
383
386 if (Params.empty())
387 return Builder;
388
389 ASTContext &AST = Builder.SemaRef.Context;
391 CD ? constructConceptSpecializationExpr(Builder.SemaRef, CD) : nullptr;
392 auto *ParamList = TemplateParameterList::Create(
395 AST, Builder.Record->getDeclContext(), SourceLocation(),
396 DeclarationName(Builder.Record->getIdentifier()), ParamList,
397 Builder.Record);
398
399 Builder.Record->setDescribedClassTemplate(Builder.Template);
400 Builder.Template->setImplicit(true);
401 Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
402
403 // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
404 // make visible.
405 Builder.Template->setPreviousDecl(Builder.PrevTemplate);
406 Builder.Record->getDeclContext()->addDecl(Builder.Template);
407 Params.clear();
408
409 return Builder;
410}
411
412Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
413 if (PH == PlaceHolder::Handle)
414 return getResourceHandleExpr();
415 if (PH == PlaceHolder::CounterHandle)
417
418 if (PH == PlaceHolder::LastStmt) {
419 assert(!StmtsList.empty() && "no statements in the list");
420 Stmt *LastStmt = StmtsList.pop_back_val();
421 assert(isa<ValueStmt>(LastStmt) && "last statement does not have a value");
422 return cast<ValueStmt>(LastStmt)->getExprStmt();
423 }
424
425 // All other placeholders are parameters (_N), and can be loaded as an
426 // LValue. It needs to be an LValue if the result expression will be used as
427 // the actual parameter for an out parameter. The dimension builtins are an
428 // example where this happens.
429 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
430 ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
431 return DeclRefExpr::Create(
432 AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
434 ParamDecl->getType().getNonReferenceType(), VK_LValue);
435}
436
437Expr *BuiltinTypeMethodBuilder::convertPlaceholder(LocalVar &Var) {
438 VarDecl *VD = Var.Decl;
439 assert(VD && "local variable is not declared");
440 return DeclRefExpr::Create(
441 VD->getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
442 false, DeclarationNameInfo(VD->getDeclName(), SourceLocation()),
443 VD->getType(), VK_LValue);
444}
445
446Expr *BuiltinTypeMethodBuilder::convertPlaceholder(QualType Ty) {
447 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
448 QualType PtrTy = AST.getPointerType(Ty);
449 // Creates a value-initialized null pointer of type Ty*.
450 return new (AST) CXXScalarValueInitExpr(
451 PtrTy, AST.getTrivialTypeSourceInfo(PtrTy, SourceLocation()),
452 SourceLocation());
453}
454
456 StringRef NameStr,
457 QualType ReturnTy,
458 bool IsConst, bool IsCtor,
459 StorageClass SC)
460 : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
461 IsCtor(IsCtor), SC(SC) {
462
463 assert((!NameStr.empty() || IsCtor) && "method needs a name");
464 assert(((IsCtor && !IsConst) || !IsCtor) && "constructor cannot be const");
465
466 ASTContext &AST = DB.SemaRef.getASTContext();
467 if (IsCtor) {
469 AST.getCanonicalTagType(DB.Record));
470 } else {
471 const IdentifierInfo &II =
472 AST.Idents.get(NameStr, tok::TokenKind::identifier);
473 Name = DeclarationName(&II);
474 }
475}
476
479 HLSLParamModifierAttr::Spelling Modifier) {
480 assert(Method == nullptr && "Cannot add param, method already created");
481 const IdentifierInfo &II = DeclBuilder.SemaRef.getASTContext().Idents.get(
482 Name, tok::TokenKind::identifier);
483 Params.emplace_back(II, Ty, Modifier);
484 return *this;
485}
487 assert(Method == nullptr &&
488 "Cannot add template param, method already created");
489 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
490 unsigned Position = static_cast<unsigned>(TemplateParamDecls.size());
492 AST, DeclBuilder.Record, SourceLocation(), SourceLocation(),
493 /* TemplateDepth */ 0, Position,
494 &AST.Idents.get(Name, tok::TokenKind::identifier),
495 /* Typename */ true,
496 /* ParameterPack */ false,
497 /* HasTypeConstraint*/ false);
498 TemplateParamDecls.push_back(Decl);
499
500 return QualType(Decl->getTypeForDecl(), 0);
501}
502
503void BuiltinTypeMethodBuilder::createDecl() {
504 assert(Method == nullptr && "Method or constructor is already created");
505
506 // create function prototype
507 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
508 SmallVector<QualType> ParamTypes;
509 SmallVector<FunctionType::ExtParameterInfo> ParamExtInfos(Params.size());
510 uint32_t ArgIndex = 0;
511
512 // Create function prototype.
513 bool UseParamExtInfo = false;
514 for (Param &MP : Params) {
515 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
516 UseParamExtInfo = true;
517 FunctionType::ExtParameterInfo &PI = ParamExtInfos[ArgIndex];
518 ParamExtInfos[ArgIndex] =
519 PI.withABI(convertParamModifierToParamABI(MP.Modifier));
520 if (!MP.Ty->isDependentType())
521 MP.Ty = getInoutParameterType(AST, MP.Ty);
522 }
523 ParamTypes.emplace_back(MP.Ty);
524 ++ArgIndex;
525 }
526
527 FunctionProtoType::ExtProtoInfo ExtInfo;
528 if (UseParamExtInfo)
529 ExtInfo.ExtParameterInfos = ParamExtInfos.data();
530 if (IsConst)
531 ExtInfo.TypeQuals.addConst();
532
533 QualType FuncTy = AST.getFunctionType(ReturnTy, ParamTypes, ExtInfo);
534
535 // Create method or constructor declaration.
536 auto *TSInfo = AST.getTrivialTypeSourceInfo(FuncTy, SourceLocation());
537 DeclarationNameInfo NameInfo = DeclarationNameInfo(Name, SourceLocation());
538 if (IsCtor)
540 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo,
541 ExplicitSpecifier(), false, /*IsInline=*/true, false,
543 else
544 Method = CXXMethodDecl::Create(
545 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo, SC,
546 false, true, ConstexprSpecKind::Unspecified, SourceLocation());
547
548 // Create params & set them to the method/constructor and function prototype.
550 unsigned CurScopeDepth = DeclBuilder.SemaRef.getCurScope()->getDepth();
551 auto FnProtoLoc =
552 Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
553 for (int I = 0, E = Params.size(); I != E; I++) {
554 Param &MP = Params[I];
555 ParmVarDecl *Parm = ParmVarDecl::Create(
556 AST, Method, SourceLocation(), SourceLocation(), &MP.NameII, MP.Ty,
557 AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None,
558 nullptr);
559 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
560 auto *Mod =
561 HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
562 Parm->addAttr(Mod);
563 }
564 Parm->setScopeInfo(CurScopeDepth, I);
565 ParmDecls.push_back(Parm);
566 FnProtoLoc.setParam(I, Parm);
567 }
568 Method->setParams({ParmDecls});
569}
570
572 ensureCompleteDecl();
573
574 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
576 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
577 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
578 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
579 HandleField->getType(), VK_LValue,
581}
582
584 ensureCompleteDecl();
585
586 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
588 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
589 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
590 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
591 HandleField->getType(), VK_LValue,
593}
594
597 ensureCompleteDecl();
598
599 assert(Var.Decl == nullptr && "local variable is already declared");
600
601 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
602 Var.Decl = VarDecl::Create(
603 AST, Method, SourceLocation(), SourceLocation(),
604 &AST.Idents.get(Var.Name, tok::TokenKind::identifier), Var.Ty,
606 DeclStmt *DS = new (AST) clang::DeclStmt(DeclGroupRef(Var.Decl),
608 StmtsList.push_back(DS);
609 return *this;
610}
611
613 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
615 AST, SourceLocation(), Method->getFunctionObjectParameterType(),
616 /*IsImplicit=*/true);
617 StmtsList.push_back(ThisExpr);
618 return *this;
619}
620
621template <typename... Ts>
624 QualType ReturnType, Ts &&...ArgSpecs) {
625 ensureCompleteDecl();
626
627 std::array<Expr *, sizeof...(ArgSpecs)> Args{
628 convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
629
630 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
631 FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
633 AST, NestedNameSpecifierLoc(), SourceLocation(), FD, false,
635
636 ExprResult Call = DeclBuilder.SemaRef.BuildCallExpr(
637 /*Scope=*/nullptr, DRE, SourceLocation(),
638 MultiExprArg(Args.data(), Args.size()), SourceLocation());
639 assert(!Call.isInvalid() && "Call to builtin cannot fail!");
640 Expr *E = Call.get();
641
642 if (!ReturnType.isNull() &&
643 !AST.hasSameUnqualifiedType(ReturnType, E->getType())) {
644 ExprResult CastResult = DeclBuilder.SemaRef.BuildCStyleCastExpr(
645 SourceLocation(), AST.getTrivialTypeSourceInfo(ReturnType),
646 SourceLocation(), E);
647 assert(!CastResult.isInvalid() && "Cast cannot fail!");
648 E = CastResult.get();
649 }
650
651 StmtsList.push_back(E);
652 return *this;
653}
654
655template <typename TLHS, typename TRHS>
657 Expr *LHSExpr = convertPlaceholder(LHS);
658 Expr *RHSExpr = convertPlaceholder(RHS);
659 Stmt *AssignStmt = BinaryOperator::Create(
660 DeclBuilder.SemaRef.getASTContext(), LHSExpr, RHSExpr, BO_Assign,
663 StmtsList.push_back(AssignStmt);
664 return *this;
665}
666
667template <typename T>
669 Expr *PtrExpr = convertPlaceholder(Ptr);
670 Expr *Deref =
671 UnaryOperator::Create(DeclBuilder.SemaRef.getASTContext(), PtrExpr,
672 UO_Deref, PtrExpr->getType()->getPointeeType(),
674 /*CanOverflow=*/false, FPOptionsOverride());
675 StmtsList.push_back(Deref);
676 return *this;
677}
678
679template <typename T>
682 ensureCompleteDecl();
683
684 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
685 auto *ResourceTypeDecl = ResourceExpr->getType()->getAsCXXRecordDecl();
686
687 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
688 FieldDecl *HandleField = nullptr;
689
690 if (ResourceTypeDecl == DeclBuilder.Record)
691 HandleField = DeclBuilder.getResourceHandleField();
692 else {
693 IdentifierInfo &II = AST.Idents.get("__handle");
694 for (auto *Decl : ResourceTypeDecl->lookup(&II)) {
695 if ((HandleField = dyn_cast<FieldDecl>(Decl)))
696 break;
697 }
698 assert(HandleField && "Resource handle field not found");
699 }
700
702 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
704 StmtsList.push_back(HandleExpr);
705 return *this;
706}
707
708template <typename ResourceT, typename ValueT>
711 ValueT HandleValue) {
712 return setFieldOnResource(ResourceRecord, HandleValue,
713 DeclBuilder.getResourceHandleField());
714}
715
716template <typename ResourceT, typename ValueT>
719 ResourceT ResourceRecord, ValueT HandleValue) {
720 return setFieldOnResource(ResourceRecord, HandleValue,
721 DeclBuilder.getResourceCounterHandleField());
722}
723
724template <typename ResourceT, typename ValueT>
725BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::setFieldOnResource(
726 ResourceT ResourceRecord, ValueT HandleValue, FieldDecl *HandleField) {
727 ensureCompleteDecl();
728
729 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
730 assert(ResourceExpr->getType()->getAsCXXRecordDecl() ==
731 HandleField->getParent() &&
732 "Getting the field from the wrong resource type.");
733
734 Expr *HandleValueExpr = convertPlaceholder(HandleValue);
735
736 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
737 MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
738 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
740 Stmt *AssignStmt = BinaryOperator::Create(
741 DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr,
742 BO_Assign, HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
744 StmtsList.push_back(AssignStmt);
745 return *this;
746}
747
748template <typename T>
749BuiltinTypeMethodBuilder &
751 ensureCompleteDecl();
752
753 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
754 assert(ResourceExpr->getType()->getAsCXXRecordDecl() == DeclBuilder.Record &&
755 "Getting the field from the wrong resource type.");
756
757 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
758 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
760 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
762 StmtsList.push_back(HandleExpr);
763 return *this;
764}
765
766template <typename T>
768 ensureCompleteDecl();
769
770 Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
771 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
772
773 QualType Ty = ReturnValueExpr->getType();
774 if (Ty->isRecordType()) {
775 // For record types, create a call to copy constructor to ensure proper copy
776 // semantics.
777 auto *ICE =
778 ImplicitCastExpr::Create(AST, Ty.withConst(), CK_NoOp, ReturnValueExpr,
779 nullptr, VK_XValue, FPOptionsOverride());
780 CXXConstructorDecl *CD = lookupCopyConstructor(Ty);
781 assert(CD && "no copy constructor found");
782 ReturnValueExpr = CXXConstructExpr::Create(
783 AST, Ty, SourceLocation(), CD, /*Elidable=*/false, {ICE},
784 /*HadMultipleCandidates=*/false, /*ListInitialization=*/false,
785 /*StdInitListInitialization=*/false,
786 /*ZeroInitListInitialization=*/false, CXXConstructionKind::Complete,
787 SourceRange());
788 }
789 StmtsList.push_back(
790 ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
791 return *this;
792}
793
795 assert(!DeclBuilder.Record->isCompleteDefinition() &&
796 "record is already complete");
797
798 ensureCompleteDecl();
799
800 if (!Method->hasBody()) {
801 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
802 assert((ReturnTy == AST.VoidTy || !StmtsList.empty()) &&
803 "nothing to return from non-void method");
804 if (ReturnTy != AST.VoidTy) {
805 if (Expr *LastExpr = dyn_cast<Expr>(StmtsList.back())) {
806 assert(AST.hasSameUnqualifiedType(LastExpr->getType(),
807 ReturnTy.getNonReferenceType()) &&
808 "Return type of the last statement must match the return type "
809 "of the method");
810 if (!isa<ReturnStmt>(LastExpr)) {
811 StmtsList.pop_back();
812 StmtsList.push_back(
813 ReturnStmt::Create(AST, SourceLocation(), LastExpr, nullptr));
814 }
815 }
816 }
817
818 Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
820 Method->setLexicalDeclContext(DeclBuilder.Record);
821 Method->setAccess(AS_public);
822 Method->addAttr(AlwaysInlineAttr::CreateImplicit(
823 AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
824 if (!TemplateParamDecls.empty()) {
825 TemplateParams = TemplateParameterList::Create(
826 AST, SourceLocation(), SourceLocation(), TemplateParamDecls,
827 SourceLocation(), nullptr);
828
829 auto *FuncTemplate = FunctionTemplateDecl::Create(AST, DeclBuilder.Record,
830 SourceLocation(), Name,
831 TemplateParams, Method);
832 FuncTemplate->setAccess(AS_public);
833 FuncTemplate->setLexicalDeclContext(DeclBuilder.Record);
834 FuncTemplate->setImplicit(true);
835 Method->setDescribedFunctionTemplate(FuncTemplate);
836 DeclBuilder.Record->addDecl(FuncTemplate);
837 } else {
838 DeclBuilder.Record->addDecl(Method);
839 }
840 }
841 return DeclBuilder;
842}
843
845 : SemaRef(SemaRef), Record(R) {
846 Record->startDefinition();
847 Template = Record->getDescribedClassTemplate();
848}
849
851 NamespaceDecl *Namespace,
852 StringRef Name)
853 : SemaRef(SemaRef), HLSLNamespace(Namespace) {
854 ASTContext &AST = SemaRef.getASTContext();
855 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
856
858 CXXRecordDecl *PrevDecl = nullptr;
859 if (SemaRef.LookupQualifiedName(Result, HLSLNamespace)) {
860 // Declaration already exists (from precompiled headers)
861 NamedDecl *Found = Result.getFoundDecl();
862 if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
863 PrevDecl = TD->getTemplatedDecl();
864 PrevTemplate = TD;
865 } else
866 PrevDecl = dyn_cast<CXXRecordDecl>(Found);
867 assert(PrevDecl && "Unexpected lookup result type.");
868 }
869
870 if (PrevDecl && PrevDecl->isCompleteDefinition()) {
871 Record = PrevDecl;
872 Template = PrevTemplate;
873 return;
874 }
875
876 Record =
877 CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
878 SourceLocation(), SourceLocation(), &II, PrevDecl);
879 Record->setImplicit(true);
880 Record->setLexicalDeclContext(HLSLNamespace);
881 Record->setHasExternalLexicalStorage();
882
883 // Don't let anyone derive from built-in types.
884 Record->addAttr(
885 FinalAttr::CreateImplicit(AST, SourceRange(), FinalAttr::Keyword_final));
886}
887
889 if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
890 HLSLNamespace->addDecl(Record);
891}
892
896 AccessSpecifier Access) {
897 assert(!Record->isCompleteDefinition() && "record is already complete");
898 assert(Record->isBeingDefined() &&
899 "Definition must be started before adding members!");
900 ASTContext &AST = Record->getASTContext();
901
902 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
903 TypeSourceInfo *MemTySource =
905 auto *Field = FieldDecl::Create(
906 AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
907 nullptr, false, InClassInitStyle::ICIS_NoInit);
908 Field->setAccess(Access);
909 Field->setImplicit(true);
910 for (Attr *A : Attrs) {
911 if (A)
912 Field->addAttr(A);
913 }
914
915 Record->addDecl(Field);
916 Fields[Name] = Field;
917 return *this;
918}
919
921BuiltinTypeDeclBuilder::addBufferHandles(ResourceClass RC, bool IsROV,
922 bool RawBuffer, bool HasCounter,
923 AccessSpecifier Access) {
924 addHandleMember(RC, ResourceDimension::Unknown, IsROV, RawBuffer, Access);
925 if (HasCounter)
926 addCounterHandleMember(RC, IsROV, RawBuffer, Access);
927 return *this;
928}
929
931BuiltinTypeDeclBuilder::addTextureHandle(ResourceClass RC, bool IsROV,
932 ResourceDimension RD,
933 AccessSpecifier Access) {
934 addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, Access);
935 return *this;
936}
937
939 addHandleMember(ResourceClass::Sampler, ResourceDimension::Unknown,
940 /*IsROV=*/false, /*RawBuffer=*/false);
941 return *this;
942}
943
945BuiltinTypeDeclBuilder::addHandleMember(ResourceClass RC, ResourceDimension RD,
946 bool IsROV, bool RawBuffer,
947 AccessSpecifier Access) {
948 return addResourceMember("__handle", RC, RD, IsROV, RawBuffer,
949 /*IsCounter=*/false, Access);
950}
951
952BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
953 ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
954 return addResourceMember("__counter_handle", RC, ResourceDimension::Unknown,
955 IsROV, RawBuffer,
956 /*IsCounter=*/true, Access);
957}
958
959BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember(
960 StringRef MemberName, ResourceClass RC, ResourceDimension RD, bool IsROV,
961 bool RawBuffer, bool IsCounter, AccessSpecifier Access) {
962 assert(!Record->isCompleteDefinition() && "record is already complete");
963
964 ASTContext &Ctx = SemaRef.getASTContext();
965 TypeSourceInfo *ElementTypeInfo =
966 Ctx.getTrivialTypeSourceInfo(getHandleElementType(), SourceLocation());
967
968 // add handle member with resource type attributes
969 QualType AttributedResTy = QualType();
971 HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
972 IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
973 RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
974 RD != ResourceDimension::Unknown
975 ? HLSLResourceDimensionAttr::CreateImplicit(Ctx, RD)
976 : nullptr,
977 ElementTypeInfo && RC != ResourceClass::Sampler
978 ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
979 : nullptr};
980 if (IsCounter)
981 Attrs.push_back(HLSLIsCounterAttr::CreateImplicit(Ctx));
982
983 if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
984 AttributedResTy))
985 addMemberVariable(MemberName, AttributedResTy, {}, Access);
986 return *this;
987}
988
989// Adds default constructor to the resource class:
990// Resource::Resource()
992 assert(!Record->isCompleteDefinition() && "record is already complete");
993
994 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
995 QualType HandleType = getResourceHandleField()->getType();
996 return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
997 false, true)
998 .callBuiltin("__builtin_hlsl_resource_uninitializedhandle", HandleType,
999 PH::Handle)
1000 .assign(PH::Handle, PH::LastStmt)
1001 .finalize();
1002}
1003
1006 if (HasCounter) {
1007 addCreateFromBindingWithImplicitCounter();
1008 addCreateFromImplicitBindingWithImplicitCounter();
1009 } else {
1010 addCreateFromBinding();
1011 addCreateFromImplicitBinding();
1012 }
1013 return *this;
1014}
1015
1016// Adds static method that initializes resource from binding:
1017//
1018// static Resource<T> __createFromBinding(unsigned registerNo,
1019// unsigned spaceNo, int range,
1020// unsigned index, const char *name) {
1021// Resource<T> tmp;
1022// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1023// tmp.__handle, registerNo, spaceNo,
1024// range, index, name);
1025// return tmp;
1026// }
1027BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
1028 assert(!Record->isCompleteDefinition() && "record is already complete");
1029
1030 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1031 ASTContext &AST = SemaRef.getASTContext();
1032 QualType HandleType = getResourceHandleField()->getType();
1033 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1034 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1035
1036 return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
1037 false, false, SC_Static)
1038 .addParam("registerNo", AST.UnsignedIntTy)
1039 .addParam("spaceNo", AST.UnsignedIntTy)
1040 .addParam("range", AST.IntTy)
1041 .addParam("index", AST.UnsignedIntTy)
1042 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1043 .declareLocalVar(TmpVar)
1044 .accessHandleFieldOnResource(TmpVar)
1045 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1046 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1047 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1048 .returnValue(TmpVar)
1049 .finalize();
1050}
1051
1052// Adds static method that initializes resource from binding:
1053//
1054// static Resource<T> __createFromImplicitBinding(unsigned orderId,
1055// unsigned spaceNo, int range,
1056// unsigned index,
1057// const char *name) {
1058// Resource<T> tmp;
1059// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1060// tmp.__handle, spaceNo,
1061// range, index, orderId, name);
1062// return tmp;
1063// }
1064BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
1065 assert(!Record->isCompleteDefinition() && "record is already complete");
1066
1067 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1068 ASTContext &AST = SemaRef.getASTContext();
1069 QualType HandleType = getResourceHandleField()->getType();
1070 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1071 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1072
1073 return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
1074 RecordType, false, false, SC_Static)
1075 .addParam("orderId", AST.UnsignedIntTy)
1076 .addParam("spaceNo", AST.UnsignedIntTy)
1077 .addParam("range", AST.IntTy)
1078 .addParam("index", AST.UnsignedIntTy)
1079 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1080 .declareLocalVar(TmpVar)
1081 .accessHandleFieldOnResource(TmpVar)
1082 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1083 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1084 PH::_4)
1085 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1086 .returnValue(TmpVar)
1087 .finalize();
1088}
1089
1090// Adds static method that initializes resource from binding:
1091//
1092// static Resource<T>
1093// __createFromBindingWithImplicitCounter(unsigned registerNo,
1094// unsigned spaceNo, int range,
1095// unsigned index, const char *name,
1096// unsigned counterOrderId) {
1097// Resource<T> tmp;
1098// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1099// tmp.__handle, registerNo, spaceNo, range, index, name);
1100// tmp.__counter_handle =
1101// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1102// tmp.__handle, counterOrderId, spaceNo);
1103// return tmp;
1104// }
1106BuiltinTypeDeclBuilder::addCreateFromBindingWithImplicitCounter() {
1107 assert(!Record->isCompleteDefinition() && "record is already complete");
1108
1109 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1110 ASTContext &AST = SemaRef.getASTContext();
1111 QualType HandleType = getResourceHandleField()->getType();
1112 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1113 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1114 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1115
1116 return BuiltinTypeMethodBuilder(*this,
1117 "__createFromBindingWithImplicitCounter",
1118 RecordType, false, false, SC_Static)
1119 .addParam("registerNo", AST.UnsignedIntTy)
1120 .addParam("spaceNo", AST.UnsignedIntTy)
1121 .addParam("range", AST.IntTy)
1122 .addParam("index", AST.UnsignedIntTy)
1123 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1124 .addParam("counterOrderId", AST.UnsignedIntTy)
1125 .declareLocalVar(TmpVar)
1126 .accessHandleFieldOnResource(TmpVar)
1127 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1128 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1129 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1130 .accessHandleFieldOnResource(TmpVar)
1131 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1132 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1133 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1134 .returnValue(TmpVar)
1135 .finalize();
1136}
1137
1138// Adds static method that initializes resource from binding:
1139//
1140// static Resource<T>
1141// __createFromImplicitBindingWithImplicitCounter(unsigned orderId,
1142// unsigned spaceNo, int range,
1143// unsigned index,
1144// const char *name,
1145// unsigned counterOrderId) {
1146// Resource<T> tmp;
1147// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1148// tmp.__handle, orderId, spaceNo, range, index, name);
1149// tmp.__counter_handle =
1150// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1151// tmp.__handle, counterOrderId, spaceNo);
1152// return tmp;
1153// }
1155BuiltinTypeDeclBuilder::addCreateFromImplicitBindingWithImplicitCounter() {
1156 assert(!Record->isCompleteDefinition() && "record is already complete");
1157
1158 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1159 ASTContext &AST = SemaRef.getASTContext();
1160 QualType HandleType = getResourceHandleField()->getType();
1161 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1162 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1163 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1164
1166 *this, "__createFromImplicitBindingWithImplicitCounter",
1167 RecordType, false, false, SC_Static)
1168 .addParam("orderId", AST.UnsignedIntTy)
1169 .addParam("spaceNo", AST.UnsignedIntTy)
1170 .addParam("range", AST.IntTy)
1171 .addParam("index", AST.UnsignedIntTy)
1172 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1173 .addParam("counterOrderId", AST.UnsignedIntTy)
1174 .declareLocalVar(TmpVar)
1175 .accessHandleFieldOnResource(TmpVar)
1176 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1177 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1178 PH::_4)
1179 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1180 .accessHandleFieldOnResource(TmpVar)
1181 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1182 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1183 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1184 .returnValue(TmpVar)
1185 .finalize();
1186}
1187
1189 assert(!Record->isCompleteDefinition() && "record is already complete");
1190
1191 ASTContext &AST = SemaRef.getASTContext();
1192 QualType RecordType = AST.getCanonicalTagType(Record);
1193 QualType ConstRecordType = RecordType.withConst();
1194 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1195
1196 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1197
1198 BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy,
1199 /*IsConst=*/false, /*IsCtor=*/true);
1200 MMB.addParam("other", ConstRecordRefType)
1202 .assign(PH::Handle, PH::LastStmt);
1203
1204 if (getResourceCounterHandleField())
1205 MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
1206 PH::LastStmt);
1207
1208 return MMB.finalize();
1209}
1210
1212 assert(!Record->isCompleteDefinition() && "record is already complete");
1213
1214 ASTContext &AST = SemaRef.getASTContext();
1215 QualType RecordType = AST.getCanonicalTagType(Record);
1216 QualType ConstRecordType = RecordType.withConst();
1217 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1218 QualType RecordRefType = AST.getLValueReferenceType(RecordType);
1219
1220 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1222 BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType);
1223 MMB.addParam("other", ConstRecordRefType)
1225 .assign(PH::Handle, PH::LastStmt);
1226
1227 if (getResourceCounterHandleField())
1228 MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
1229 PH::LastStmt);
1230
1231 return MMB.returnThis().finalize();
1232}
1233
1236 assert(!Record->isCompleteDefinition() && "record is already complete");
1237 ASTContext &AST = Record->getASTContext();
1238
1239 uint32_t VecSize = 1;
1240 if (Dim != ResourceDimension::Unknown)
1241 VecSize = getResourceDimensions(Dim);
1242
1243 QualType IndexTy = VecSize > 1
1244 ? AST.getExtVectorType(AST.UnsignedIntTy, VecSize)
1245 : AST.UnsignedIntTy;
1246
1247 DeclarationName Subscript =
1248 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1249
1250 addHandleAccessFunction(Subscript, /*IsConst=*/true, /*IsRef=*/true, IndexTy);
1251 if (getResourceAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV)
1252 addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true,
1253 IndexTy);
1254
1255 return *this;
1256}
1257
1259 assert(!Record->isCompleteDefinition() && "record is already complete");
1260
1261 ASTContext &AST = Record->getASTContext();
1262 IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
1263 DeclarationName Load(&II);
1264 // TODO: We also need versions with status for CheckAccessFullyMapped.
1265 addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false,
1266 AST.UnsignedIntTy);
1267 addLoadWithStatusFunction(Load, /*IsConst=*/false);
1268
1269 return *this;
1270}
1271
1274 assert(!Record->isCompleteDefinition() && "record is already complete");
1275 ASTContext &AST = Record->getASTContext();
1276 uint32_t VecSize = getResourceDimensions(Dim);
1277 QualType IntTy = AST.IntTy;
1278 QualType OffsetTy = AST.getExtVectorType(IntTy, VecSize);
1279 QualType LocationTy = AST.getExtVectorType(IntTy, VecSize + 1);
1280 QualType ReturnType = getHandleElementType();
1281
1282 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1283
1284 // T Load(int3 location)
1285 BuiltinTypeMethodBuilder(*this, "Load", ReturnType)
1286 .addParam("Location", LocationTy)
1287 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1288 PH::_0)
1289 .finalize();
1290
1291 // T Load(int3 location, int2 offset)
1292 return BuiltinTypeMethodBuilder(*this, "Load", ReturnType)
1293 .addParam("Location", LocationTy)
1294 .addParam("Offset", OffsetTy)
1295 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1296 PH::_0, PH::_1)
1297 .finalize();
1298}
1299
1302 assert(!Record->isCompleteDefinition() && "record is already complete");
1303
1304 ASTContext &AST = SemaRef.getASTContext();
1305
1306 auto AddLoads = [&](StringRef MethodName, QualType ReturnType) {
1307 IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
1308 DeclarationName Load(&II);
1309
1310 addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false,
1311 AST.UnsignedIntTy, ReturnType);
1312 addLoadWithStatusFunction(Load, /*IsConst=*/false, ReturnType);
1313 };
1314
1315 AddLoads("Load", AST.UnsignedIntTy);
1316 AddLoads("Load2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
1317 AddLoads("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
1318 AddLoads("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
1319 AddLoads("Load", AST.DependentTy); // Templated version
1320 return *this;
1321}
1322
1325 assert(!Record->isCompleteDefinition() && "record is already complete");
1326
1327 ASTContext &AST = SemaRef.getASTContext();
1328
1329 auto AddStore = [&](StringRef MethodName, QualType ValueType) {
1330 IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
1331 DeclarationName Store(&II);
1332
1333 addStoreFunction(Store, /*IsConst=*/false, ValueType);
1334 };
1335
1336 AddStore("Store", AST.UnsignedIntTy);
1337 AddStore("Store2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
1338 AddStore("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
1339 AddStore("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
1340 AddStore("Store", AST.DependentTy); // Templated version
1341
1342 return *this;
1343}
1344
1347 assert(!Record->isCompleteDefinition() && "record is already complete");
1348 ASTContext &AST = Record->getASTContext();
1349 QualType ReturnType = getHandleElementType();
1350 QualType SamplerStateType =
1351 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1352 uint32_t VecSize = getResourceDimensions(Dim);
1353 QualType FloatTy = AST.FloatTy;
1354 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1355 QualType IntTy = AST.IntTy;
1356 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1357 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1358
1359 // T Sample(SamplerState s, float2 location)
1360 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1361 .addParam("Sampler", SamplerStateType)
1362 .addParam("Location", Float2Ty)
1363 .accessHandleFieldOnResource(PH::_0)
1364 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1365 PH::LastStmt, PH::_1)
1366 .returnValue(PH::LastStmt)
1367 .finalize();
1368
1369 // T Sample(SamplerState s, float2 location, int2 offset)
1370 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1371 .addParam("Sampler", SamplerStateType)
1372 .addParam("Location", Float2Ty)
1373 .addParam("Offset", Int2Ty)
1374 .accessHandleFieldOnResource(PH::_0)
1375 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1376 PH::LastStmt, PH::_1, PH::_2)
1377 .returnValue(PH::LastStmt)
1378 .finalize();
1379
1380 // T Sample(SamplerState s, float2 location, int2 offset, float clamp)
1381 return BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1382 .addParam("Sampler", SamplerStateType)
1383 .addParam("Location", Float2Ty)
1384 .addParam("Offset", Int2Ty)
1385 .addParam("Clamp", FloatTy)
1386 .accessHandleFieldOnResource(PH::_0)
1387 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1388 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1389 .returnValue(PH::LastStmt)
1390 .finalize();
1391}
1392
1395 assert(!Record->isCompleteDefinition() && "record is already complete");
1396 ASTContext &AST = Record->getASTContext();
1397 QualType ReturnType = getHandleElementType();
1398 QualType SamplerStateType =
1399 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1400 uint32_t VecSize = getResourceDimensions(Dim);
1401 QualType FloatTy = AST.FloatTy;
1402 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1403 QualType IntTy = AST.IntTy;
1404 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1405 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1406
1407 // T SampleBias(SamplerState s, float2 location, float bias)
1408 BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1409 .addParam("Sampler", SamplerStateType)
1410 .addParam("Location", Float2Ty)
1411 .addParam("Bias", FloatTy)
1412 .accessHandleFieldOnResource(PH::_0)
1413 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1414 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1415 .returnValue(PH::LastStmt)
1416 .finalize();
1417
1418 // T SampleBias(SamplerState s, float2 location, float bias, int2 offset)
1419 BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1420 .addParam("Sampler", SamplerStateType)
1421 .addParam("Location", Float2Ty)
1422 .addParam("Bias", FloatTy)
1423 .addParam("Offset", Int2Ty)
1424 .accessHandleFieldOnResource(PH::_0)
1425 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1426 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1427 .returnValue(PH::LastStmt)
1428 .finalize();
1429
1430 // T SampleBias(SamplerState s, float2 location, float bias, int2 offset,
1431 // float clamp)
1432 return BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1433 .addParam("Sampler", SamplerStateType)
1434 .addParam("Location", Float2Ty)
1435 .addParam("Bias", FloatTy)
1436 .addParam("Offset", Int2Ty)
1437 .addParam("Clamp", FloatTy)
1438 .accessHandleFieldOnResource(PH::_0)
1439 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1440 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1441 .returnValue(PH::LastStmt)
1442 .finalize();
1443}
1444
1447 assert(!Record->isCompleteDefinition() && "record is already complete");
1448 ASTContext &AST = Record->getASTContext();
1449 QualType ReturnType = getHandleElementType();
1450 QualType SamplerStateType =
1451 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1452 uint32_t VecSize = getResourceDimensions(Dim);
1453 QualType FloatTy = AST.FloatTy;
1454 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1455 QualType IntTy = AST.IntTy;
1456 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1457 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1458
1459 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy)
1460 BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1461 .addParam("Sampler", SamplerStateType)
1462 .addParam("Location", Float2Ty)
1463 .addParam("DDX", Float2Ty)
1464 .addParam("DDY", Float2Ty)
1465 .accessHandleFieldOnResource(PH::_0)
1466 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1467 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1468 .returnValue(PH::LastStmt)
1469 .finalize();
1470
1471 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy,
1472 // int2 offset)
1473 BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1474 .addParam("Sampler", SamplerStateType)
1475 .addParam("Location", Float2Ty)
1476 .addParam("DDX", Float2Ty)
1477 .addParam("DDY", Float2Ty)
1478 .addParam("Offset", Int2Ty)
1479 .accessHandleFieldOnResource(PH::_0)
1480 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1481 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1482 .returnValue(PH::LastStmt)
1483 .finalize();
1484
1485 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy,
1486 // int2 offset, float clamp)
1487 return BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1488 .addParam("Sampler", SamplerStateType)
1489 .addParam("Location", Float2Ty)
1490 .addParam("DDX", Float2Ty)
1491 .addParam("DDY", Float2Ty)
1492 .addParam("Offset", Int2Ty)
1493 .addParam("Clamp", FloatTy)
1494 .accessHandleFieldOnResource(PH::_0)
1495 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1496 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4,
1497 PH::_5)
1498 .returnValue(PH::LastStmt)
1499 .finalize();
1500}
1501
1504 assert(!Record->isCompleteDefinition() && "record is already complete");
1505 ASTContext &AST = Record->getASTContext();
1506 QualType ReturnType = getHandleElementType();
1507 QualType SamplerStateType =
1508 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1509 uint32_t VecSize = getResourceDimensions(Dim);
1510 QualType FloatTy = AST.FloatTy;
1511 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1512 QualType IntTy = AST.IntTy;
1513 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1514 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1515
1516 // T SampleLevel(SamplerState s, float2 location, float lod)
1517 BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
1518 .addParam("Sampler", SamplerStateType)
1519 .addParam("Location", Float2Ty)
1520 .addParam("LOD", FloatTy)
1521 .accessHandleFieldOnResource(PH::_0)
1522 .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
1523 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1524 .returnValue(PH::LastStmt)
1525 .finalize();
1526
1527 // T SampleLevel(SamplerState s, float2 location, float lod, int2 offset)
1528 return BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
1529 .addParam("Sampler", SamplerStateType)
1530 .addParam("Location", Float2Ty)
1531 .addParam("LOD", FloatTy)
1532 .addParam("Offset", Int2Ty)
1533 .accessHandleFieldOnResource(PH::_0)
1534 .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
1535 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1536 .returnValue(PH::LastStmt)
1537 .finalize();
1538}
1539
1542 assert(!Record->isCompleteDefinition() && "record is already complete");
1543 ASTContext &AST = Record->getASTContext();
1544 QualType ReturnType = AST.FloatTy;
1545 QualType SamplerComparisonStateType = lookupBuiltinType(
1546 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1547 uint32_t VecSize = getResourceDimensions(Dim);
1548 QualType FloatTy = AST.FloatTy;
1549 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1550 QualType IntTy = AST.IntTy;
1551 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1552 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1553
1554 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value)
1555 BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1556 .addParam("Sampler", SamplerComparisonStateType)
1557 .addParam("Location", Float2Ty)
1558 .addParam("CompareValue", FloatTy)
1559 .accessHandleFieldOnResource(PH::_0)
1560 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1561 PH::LastStmt, PH::_1, PH::_2)
1562 .returnValue(PH::LastStmt)
1563 .finalize();
1564
1565 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value,
1566 // int2 offset)
1567 BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1568 .addParam("Sampler", SamplerComparisonStateType)
1569 .addParam("Location", Float2Ty)
1570 .addParam("CompareValue", FloatTy)
1571 .addParam("Offset", Int2Ty)
1572 .accessHandleFieldOnResource(PH::_0)
1573 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1574 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1575 .returnValue(PH::LastStmt)
1576 .finalize();
1577
1578 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value,
1579 // int2 offset, float clamp)
1580 return BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1581 .addParam("Sampler", SamplerComparisonStateType)
1582 .addParam("Location", Float2Ty)
1583 .addParam("CompareValue", FloatTy)
1584 .addParam("Offset", Int2Ty)
1585 .addParam("Clamp", FloatTy)
1586 .accessHandleFieldOnResource(PH::_0)
1587 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1588 PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1589 .returnValue(PH::LastStmt)
1590 .finalize();
1591}
1592
1595 assert(!Record->isCompleteDefinition() && "record is already complete");
1596 ASTContext &AST = Record->getASTContext();
1597 QualType ReturnType = AST.FloatTy;
1598 QualType SamplerComparisonStateType = lookupBuiltinType(
1599 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1600 uint32_t VecSize = getResourceDimensions(Dim);
1601 QualType FloatTy = AST.FloatTy;
1602 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1603 QualType IntTy = AST.IntTy;
1604 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1605 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1606
1607 // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
1608 // compare_value)
1609 BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
1610 .addParam("Sampler", SamplerComparisonStateType)
1611 .addParam("Location", Float2Ty)
1612 .addParam("CompareValue", FloatTy)
1613 .accessHandleFieldOnResource(PH::_0)
1614 .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
1615 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1616 .returnValue(PH::LastStmt)
1617 .finalize();
1618
1619 // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
1620 // compare_value, int2 offset)
1621 return BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
1622 .addParam("Sampler", SamplerComparisonStateType)
1623 .addParam("Location", Float2Ty)
1624 .addParam("CompareValue", FloatTy)
1625 .addParam("Offset", Int2Ty)
1626 .accessHandleFieldOnResource(PH::_0)
1627 .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
1628 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1629 .returnValue(PH::LastStmt)
1630 .finalize();
1631}
1632
1633QualType BuiltinTypeDeclBuilder::getGatherReturnType() {
1634 ASTContext &AST = SemaRef.getASTContext();
1635 QualType T = getHandleElementType();
1636 if (T.isNull())
1637 return QualType();
1638
1639 if (const auto *VT = T->getAs<VectorType>())
1640 T = VT->getElementType();
1641 else if (const auto *DT = T->getAs<DependentSizedExtVectorType>())
1642 T = DT->getElementType();
1643
1644 return AST.getExtVectorType(T, 4);
1645}
1646
1649 assert(!Record->isCompleteDefinition() && "record is already complete");
1650 ASTContext &AST = Record->getASTContext();
1651 QualType ReturnType = getGatherReturnType();
1652
1653 QualType SamplerStateType =
1654 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1655 uint32_t VecSize = getResourceDimensions(Dim);
1656 QualType LocationTy = AST.FloatTy;
1657 QualType Float2Ty = AST.getExtVectorType(LocationTy, VecSize);
1658 QualType IntTy = AST.IntTy;
1659 QualType OffsetTy = AST.getExtVectorType(IntTy, VecSize);
1660 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1661
1662 // Overloads for Gather, GatherRed, GatherGreen, GatherBlue, GatherAlpha
1663 struct GatherVariant {
1664 const char *Name;
1665 int Component;
1666 };
1667 GatherVariant Variants[] = {{"Gather", 0},
1668 {"GatherRed", 0},
1669 {"GatherGreen", 1},
1670 {"GatherBlue", 2},
1671 {"GatherAlpha", 3}};
1672
1673 for (const auto &V : Variants) {
1674 // ret GatherVariant(SamplerState s, float2 location)
1675 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
1676 .addParam("Sampler", SamplerStateType)
1677 .addParam("Location", Float2Ty)
1678 .accessHandleFieldOnResource(PH::_0)
1679 .callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
1680 PH::LastStmt, PH::_1,
1681 getConstantUnsignedIntExpr(V.Component))
1682 .finalize();
1683
1684 // ret GatherVariant(SamplerState s, float2 location, int2 offset)
1685 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
1686 .addParam("Sampler", SamplerStateType)
1687 .addParam("Location", Float2Ty)
1688 .addParam("Offset", OffsetTy)
1689 .accessHandleFieldOnResource(PH::_0)
1690 .callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
1691 PH::LastStmt, PH::_1,
1692 getConstantUnsignedIntExpr(V.Component), PH::_2)
1693 .finalize();
1694 }
1695
1696 return *this;
1697}
1698
1701 assert(!Record->isCompleteDefinition() && "record is already complete");
1702 ASTContext &AST = Record->getASTContext();
1703 QualType ReturnType = AST.getExtVectorType(AST.FloatTy, 4);
1704
1705 QualType SamplerComparisonStateType = lookupBuiltinType(
1706 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1707 uint32_t VecSize = getResourceDimensions(Dim);
1708 QualType FloatTy = AST.FloatTy;
1709 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1710 QualType IntTy = AST.IntTy;
1711 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1712 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1713
1714 // Overloads for GatherCmp, GatherCmpRed, GatherCmpGreen, GatherCmpBlue,
1715 // GatherCmpAlpha
1716 struct GatherVariant {
1717 const char *Name;
1718 int Component;
1719 };
1720 GatherVariant Variants[] = {{"GatherCmp", 0},
1721 {"GatherCmpRed", 0},
1722 {"GatherCmpGreen", 1},
1723 {"GatherCmpBlue", 2},
1724 {"GatherCmpAlpha", 3}};
1725
1726 for (const auto &V : Variants) {
1727 // ret GatherCmpVariant(SamplerComparisonState s, float2 location, float
1728 // compare_value)
1729 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
1730 .addParam("Sampler", SamplerComparisonStateType)
1731 .addParam("Location", Float2Ty)
1732 .addParam("CompareValue", FloatTy)
1733 .accessHandleFieldOnResource(PH::_0)
1734 .callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
1735 PH::Handle, PH::LastStmt, PH::_1, PH::_2,
1736 getConstantUnsignedIntExpr(V.Component))
1737 .finalize();
1738
1739 // ret GatherCmpVariant(SamplerComparisonState s, float2 location, float
1740 // compare_value, int2 offset)
1741 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
1742 .addParam("Sampler", SamplerComparisonStateType)
1743 .addParam("Location", Float2Ty)
1744 .addParam("CompareValue", FloatTy)
1745 .addParam("Offset", Int2Ty)
1746 .accessHandleFieldOnResource(PH::_0)
1747 .callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
1748 PH::Handle, PH::LastStmt, PH::_1, PH::_2,
1749 getConstantUnsignedIntExpr(V.Component), PH::_3)
1750 .finalize();
1751 }
1752
1753 return *this;
1754}
1755
1756FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
1757 auto I = Fields.find("__handle");
1758 assert(I != Fields.end() &&
1759 I->second->getType()->isHLSLAttributedResourceType() &&
1760 "record does not have resource handle field");
1761 return I->second;
1762}
1763
1764FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField() const {
1765 auto I = Fields.find("__counter_handle");
1766 if (I == Fields.end() ||
1767 !I->second->getType()->isHLSLAttributedResourceType())
1768 return nullptr;
1769 return I->second;
1770}
1771
1772QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
1773 assert(Template && "record it not a template");
1774 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
1775 Template->getTemplateParameters()->getParam(0))) {
1776 return QualType(TTD->getTypeForDecl(), 0);
1777 }
1778 return QualType();
1779}
1780
1781QualType BuiltinTypeDeclBuilder::getHandleElementType() {
1782 if (Template)
1783 return getFirstTemplateTypeParam();
1784
1785 if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
1786 const auto &Args = Spec->getTemplateArgs();
1787 if (Args.size() > 0 && Args[0].getKind() == TemplateArgument::Type)
1788 return Args[0].getAsType();
1789 }
1790
1791 // TODO: Should we default to VoidTy? Using `i8` is arguably ambiguous.
1792 return SemaRef.getASTContext().Char8Ty;
1793}
1794
1795HLSLAttributedResourceType::Attributes
1796BuiltinTypeDeclBuilder::getResourceAttrs() const {
1797 QualType HandleType = getResourceHandleField()->getType();
1798 return cast<HLSLAttributedResourceType>(HandleType)->getAttrs();
1799}
1800
1802 assert(!Record->isCompleteDefinition() && "record is already complete");
1803 assert(Record->isBeingDefined() &&
1804 "Definition must be started before completing it.");
1805
1806 Record->completeDefinition();
1807 return *this;
1808}
1809
1810Expr *BuiltinTypeDeclBuilder::getConstantIntExpr(int value) {
1811 ASTContext &AST = SemaRef.getASTContext();
1813 AST, llvm::APInt(AST.getTypeSize(AST.IntTy), value, true), AST.IntTy,
1814 SourceLocation());
1815}
1816
1817Expr *BuiltinTypeDeclBuilder::getConstantUnsignedIntExpr(unsigned value) {
1818 ASTContext &AST = SemaRef.getASTContext();
1820 AST, llvm::APInt(AST.getTypeSize(AST.UnsignedIntTy), value),
1822}
1823
1829
1832 ArrayRef<QualType> DefaultTypes,
1833 ConceptDecl *CD) {
1834 if (Record->isCompleteDefinition()) {
1835 assert(Template && "existing record it not a template");
1836 assert(Template->getTemplateParameters()->size() == Names.size() &&
1837 "template param count mismatch");
1838 return *this;
1839 }
1840
1841 assert((DefaultTypes.empty() || DefaultTypes.size() == Names.size()) &&
1842 "template default argument count mismatch");
1843
1845 for (unsigned i = 0; i < Names.size(); ++i) {
1846 QualType DefaultTy = DefaultTypes.empty() ? QualType() : DefaultTypes[i];
1847 Builder.addTypeParameter(Names[i], DefaultTy);
1848 }
1849 return Builder.finalizeTemplateArgs(CD);
1850}
1851
1853 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1854 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
1855 return BuiltinTypeMethodBuilder(*this, "IncrementCounter", UnsignedIntTy)
1856 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
1857 PH::CounterHandle, getConstantIntExpr(1))
1858 .finalize();
1859}
1860
1862 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1863 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
1864 return BuiltinTypeMethodBuilder(*this, "DecrementCounter", UnsignedIntTy)
1865 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
1866 PH::CounterHandle, getConstantIntExpr(-1))
1867 .finalize();
1868}
1869
1871 DeclarationName &Name, bool IsConst, QualType ReturnTy) {
1872 assert(!Record->isCompleteDefinition() && "record is already complete");
1873 ASTContext &AST = SemaRef.getASTContext();
1874 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1875 bool NeedsTypedBuiltin = !ReturnTy.isNull();
1876
1877 // The empty QualType is a placeholder. The actual return type is set below.
1878 BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConst);
1879
1880 if (!NeedsTypedBuiltin)
1881 ReturnTy = getHandleElementType();
1882 if (ReturnTy == AST.DependentTy)
1883 ReturnTy = MMB.addTemplateTypeParam("element_type");
1884 MMB.ReturnTy = ReturnTy;
1885
1886 MMB.addParam("Index", AST.UnsignedIntTy)
1887 .addParam("Status", AST.UnsignedIntTy,
1888 HLSLParamModifierAttr::Keyword_out);
1889
1890 if (NeedsTypedBuiltin)
1891 MMB.callBuiltin("__builtin_hlsl_resource_load_with_status_typed", ReturnTy,
1892 PH::Handle, PH::_0, PH::_1, ReturnTy);
1893 else
1894 MMB.callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy,
1895 PH::Handle, PH::_0, PH::_1);
1896
1897 return MMB.finalize();
1898}
1899
1901 DeclarationName &Name, bool IsConst, bool IsRef, QualType IndexTy,
1902 QualType ElemTy) {
1903 assert(!Record->isCompleteDefinition() && "record is already complete");
1904 ASTContext &AST = SemaRef.getASTContext();
1905 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1906 bool NeedsTypedBuiltin = !ElemTy.isNull();
1907
1908 // The empty QualType is a placeholder. The actual return type is set below.
1909 BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConst);
1910
1911 if (!NeedsTypedBuiltin)
1912 ElemTy = getHandleElementType();
1913 if (ElemTy == AST.DependentTy)
1914 ElemTy = MMB.addTemplateTypeParam("element_type");
1915 QualType AddrSpaceElemTy =
1917 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
1918 QualType ReturnTy;
1919
1920 if (IsRef) {
1921 ReturnTy = AddrSpaceElemTy;
1922 if (IsConst)
1923 ReturnTy.addConst();
1924 ReturnTy = AST.getLValueReferenceType(ReturnTy);
1925 } else {
1926 ReturnTy = ElemTy;
1927 if (IsConst)
1928 ReturnTy.addConst();
1929 }
1930 MMB.ReturnTy = ReturnTy;
1931
1932 MMB.addParam("Index", IndexTy);
1933
1934 if (NeedsTypedBuiltin)
1935 MMB.callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
1936 PH::Handle, PH::_0, ElemTy);
1937 else
1938 MMB.callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
1939 PH::_0);
1940
1941 return MMB.dereference(PH::LastStmt).finalize();
1942}
1943
1946 QualType ValueTy) {
1947 assert(!Record->isCompleteDefinition() && "record is already complete");
1948 ASTContext &AST = SemaRef.getASTContext();
1949 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1950
1951 BuiltinTypeMethodBuilder MMB(*this, Name, AST.VoidTy, IsConst);
1952
1953 if (ValueTy == AST.DependentTy)
1954 ValueTy = MMB.addTemplateTypeParam("element_type");
1955 QualType AddrSpaceElemTy =
1957 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
1958
1959 return MMB.addParam("Index", AST.UnsignedIntTy)
1960 .addParam("Value", ValueTy)
1961 .callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
1962 PH::Handle, PH::_0, ValueTy)
1963 .dereference(PH::LastStmt)
1964 .assign(PH::LastStmt, PH::_1)
1965 .finalize();
1966}
1967
1969 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1970 ASTContext &AST = SemaRef.getASTContext();
1971 QualType ElemTy = getHandleElementType();
1972 QualType AddrSpaceElemTy =
1974 return BuiltinTypeMethodBuilder(*this, "Append", AST.VoidTy)
1975 .addParam("value", ElemTy)
1976 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
1977 PH::CounterHandle, getConstantIntExpr(1))
1978 .callBuiltin("__builtin_hlsl_resource_getpointer",
1979 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
1980 PH::LastStmt)
1981 .dereference(PH::LastStmt)
1982 .assign(PH::LastStmt, PH::_0)
1983 .finalize();
1984}
1985
1987 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1988 ASTContext &AST = SemaRef.getASTContext();
1989 QualType ElemTy = getHandleElementType();
1990 QualType AddrSpaceElemTy =
1992 return BuiltinTypeMethodBuilder(*this, "Consume", ElemTy)
1993 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
1994 PH::CounterHandle, getConstantIntExpr(-1))
1995 .callBuiltin("__builtin_hlsl_resource_getpointer",
1996 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
1997 PH::LastStmt)
1998 .dereference(PH::LastStmt)
1999 .finalize();
2000}
2001
2004 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2005 ASTContext &AST = SemaRef.getASTContext();
2006 QualType UIntTy = AST.UnsignedIntTy;
2007
2008 QualType HandleTy = getResourceHandleField()->getType();
2009 auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr());
2010
2011 // Structured buffers except {RW}ByteAddressBuffer have overload
2012 // GetDimensions(out uint numStructs, out uint stride).
2013 if (AttrResTy->getAttrs().RawBuffer &&
2014 AttrResTy->getContainedType() != AST.Char8Ty) {
2015 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
2016 .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out)
2017 .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out)
2018 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
2019 PH::Handle, PH::_0)
2020 .callBuiltin("__builtin_hlsl_resource_getstride", QualType(),
2021 PH::Handle, PH::_1)
2022 .finalize();
2023 }
2024
2025 // Typed buffers and {RW}ByteAddressBuffer have overload
2026 // GetDimensions(out uint dim).
2027 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
2028 .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out)
2029 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
2030 PH::Handle, PH::_0)
2031 .finalize();
2032}
2033
2034} // namespace hlsl
2035} // namespace clang
Defines the clang::ASTContext interface.
#define V(N, I)
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
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:226
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.
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:226
DeclarationNameTable DeclarationNames
Definition ASTContext.h:802
CanQualType FloatTy
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.
CanQualType DependentTy
IdentifierTable & Idents
Definition ASTContext.h:798
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
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 getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
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
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
CanQualType Char8Ty
Attr - This represents one attribute.
Definition Attr.h:46
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:5094
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:2611
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:2986
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
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:2506
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
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:399
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:1273
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:488
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1632
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
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.
Represents an extended vector type where either the type or size is dependent.
Definition TypeBase.h:4151
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:3175
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3411
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:4701
Represents a function declaration or definition.
Definition Decl.h:2015
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2226
static FunctionTemplateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl)
Create a function template node.
Interesting information about a specific parameter that can't simply be reflected in parameter's type...
Definition TypeBase.h:4579
ExtParameterInfo withABI(ParameterABI kind) const
Definition TypeBase.h:4593
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:2073
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:975
Represents the results of name lookup.
Definition Lookup.h:147
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3367
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:3428
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:1805
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:2958
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType withConst() const
Definition TypeBase.h:1165
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1162
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8431
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:8616
static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
Create a return statement.
Definition Stmt.cpp:1290
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:868
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:1137
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9402
@ LookupTagName
Tag name lookup, which finds the names of enums, classes, structs, and unions.
Definition Sema.h:9405
ASTContext & getASTContext() const
Definition Sema.h:939
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition Stmt.h:86
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3833
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
Location wrapper for a TemplateArgument.
Represents a template argument.
@ Type
The template argument is a type.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Stores a list of template parameters for a TemplateDecl and its derived classes.
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:8402
The base class of the type hierarchy.
Definition TypeBase.h:1866
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:754
bool isRecordType() const
Definition TypeBase.h:8795
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:5151
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:2163
Represents a GCC generic vector type.
Definition TypeBase.h:4225
BuiltinTypeDeclBuilder & addStoreFunction(DeclarationName &Name, bool IsConst, QualType ValueType)
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 & addArraySubscriptOperators(ResourceDimension Dim=ResourceDimension::Unknown)
BuiltinTypeDeclBuilder & addLoadWithStatusFunction(DeclarationName &Name, bool IsConst, QualType ReturnTy=QualType())
BuiltinTypeDeclBuilder & addSampleGradMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addHandleAccessFunction(DeclarationName &Name, bool IsConst, bool IsRef, QualType IndexTy, QualType ElemTy=QualType())
BuiltinTypeDeclBuilder & addGetDimensionsMethodForBuffer()
BuiltinTypeDeclBuilder & addGatherCmpMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addSampleBiasMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addBufferHandles(ResourceClass RC, bool IsROV, bool RawBuffer, bool HasCounter, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addByteAddressBufferStoreMethods()
BuiltinTypeDeclBuilder & addTextureHandle(ResourceClass RC, bool IsROV, ResourceDimension RD, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addTextureLoadMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addSampleLevelMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addByteAddressBufferLoadMethods()
BuiltinTypeDeclBuilder & addSampleMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addStaticInitializationFunctions(bool HasCounter)
BuiltinTypeDeclBuilder & addSampleCmpLevelZeroMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addGatherMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addSampleCmpMethods(ResourceDimension Dim)
uint32_t getResourceDimensions(llvm::dxil::ResourceDimension Dim)
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
MutableArrayRef< Expr * > MultiExprArg
Definition Ownership.h:259
@ Result
The result type of a method or function.
Definition TypeBase.h:905
ParameterABI
Kinds of parameter ABI.
Definition Specifiers.h:378
@ 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
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Other
Other implicit parameter.
Definition Decl.h:1761
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...
BuiltinTypeMethodBuilder & addParam(StringRef Name, QualType Ty, HLSLParamModifierAttr::Spelling Modifier=HLSLParamModifierAttr::Keyword_in)
BuiltinTypeMethodBuilder & callBuiltin(StringRef BuiltinName, QualType ReturnType, Ts &&...ArgSpecs)
BuiltinTypeMethodBuilder & accessHandleFieldOnResource(T ResourceRecord)
BuiltinTypeMethodBuilder & operator=(const BuiltinTypeMethodBuilder &Other)=delete
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)