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"
19#include "clang/AST/Expr.h"
21#include "clang/AST/Stmt.h"
22#include "clang/AST/Type.h"
25#include "clang/Sema/Lookup.h"
26#include "clang/Sema/Sema.h"
27#include "clang/Sema/SemaHLSL.h"
28#include "llvm/ADT/SmallVector.h"
29
30using namespace llvm::hlsl;
31
32namespace clang {
33
34namespace hlsl {
35
36namespace {
37
38static FunctionDecl *lookupBuiltinFunction(Sema &S, StringRef Name) {
39 IdentifierInfo &II =
40 S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
41 DeclarationNameInfo NameInfo =
42 DeclarationNameInfo(DeclarationName(&II), SourceLocation());
43 LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
44 // AllowBuiltinCreation is false but LookupDirect will create
45 // the builtin when searching the global scope anyways...
46 S.LookupName(R, S.getCurScope());
47 // FIXME: If the builtin function was user-declared in global scope,
48 // this assert *will* fail. Should this call LookupBuiltin instead?
49 assert(R.isSingleResult() &&
50 "Since this is a builtin it should always resolve!");
51 return cast<FunctionDecl>(R.getFoundDecl());
52}
53
54static QualType lookupBuiltinType(Sema &S, StringRef Name, DeclContext *DC) {
55 IdentifierInfo &II =
56 S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
57 LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
58 S.LookupQualifiedName(Result, DC);
59 assert(!Result.empty() && "Builtin type not found");
60 QualType Ty =
61 S.getASTContext().getTypeDeclType(Result.getAsSingle<TypeDecl>());
62 S.RequireCompleteType(SourceLocation(), Ty,
63 diag::err_tentative_def_incomplete_type);
64 return Ty;
65}
66
67CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
68 assert(ResTy->isRecordType() && "not a CXXRecord type");
69 for (auto *CD : ResTy->getAsCXXRecordDecl()->ctors())
70 if (CD->isCopyConstructor())
71 return CD;
72 return nullptr;
73}
74
76convertParamModifierToParamABI(HLSLParamModifierAttr::Spelling Modifier) {
77 assert(Modifier != HLSLParamModifierAttr::Spelling::Keyword_in &&
78 "HLSL 'in' parameters modifier cannot be converted to ParameterABI");
79 switch (Modifier) {
80 case HLSLParamModifierAttr::Spelling::Keyword_out:
82 case HLSLParamModifierAttr::Spelling::Keyword_inout:
84 default:
85 llvm_unreachable("Invalid HLSL parameter modifier");
86 }
87}
88
89QualType getInoutParameterType(ASTContext &AST, QualType Ty) {
90 assert(!Ty->isReferenceType() &&
91 "Pointer and reference types cannot be inout or out parameters");
92 Ty = AST.getLValueReferenceType(Ty);
93 Ty.addRestrict();
94 return Ty;
95}
96
97} // namespace
98
99// Builder for template arguments of builtin types. Used internally
100// by BuiltinTypeDeclBuilder.
116
117// Builder for methods or constructors of builtin types. Allows creating methods
118// or constructors of builtin types using the builder pattern like this:
119//
120// BuiltinTypeMethodBuilder(RecordBuilder, "MethodName", ReturnType)
121// .addParam("param_name", Type, InOutModifier)
122// .callBuiltin("builtin_name", BuiltinParams...)
123// .finalize();
124//
125// The builder needs to have all of the parameters before it can create
126// a CXXMethodDecl or CXXConstructorDecl. It collects them in addParam calls and
127// when a first method that builds the body is called or when access to 'this`
128// is needed it creates the CXXMethodDecl/CXXConstructorDecl and ParmVarDecls
129// instances. These can then be referenced from the body building methods.
130// Destructor or an explicit call to finalize() will complete the method
131// definition.
132//
133// The callBuiltin helper method accepts constants via `Expr *` or placeholder
134// value arguments to indicate which function arguments to forward to the
135// builtin.
136//
137// If the method that is being built has a non-void return type the
138// finalize() will create a return statement with the value of the last
139// statement (unless the last statement is already a ReturnStmt or the return
140// value is void).
142private:
143 struct Param {
144 const IdentifierInfo &NameII;
145 QualType Ty;
146 HLSLParamModifierAttr::Spelling Modifier;
147 Param(const IdentifierInfo &NameII, QualType Ty,
148 HLSLParamModifierAttr::Spelling Modifier)
149 : NameII(NameII), Ty(Ty), Modifier(Modifier) {}
150 };
151
152 struct LocalVar {
153 StringRef Name;
154 QualType Ty;
155 VarDecl *Decl;
156 LocalVar(StringRef Name, QualType Ty) : Name(Name), Ty(Ty), Decl(nullptr) {}
157 };
158
159 BuiltinTypeDeclBuilder &DeclBuilder;
160 DeclarationName Name;
161 QualType ReturnTy;
162 // method or constructor declaration
163 // (CXXConstructorDecl derives from CXXMethodDecl)
164 CXXMethodDecl *Method;
165 bool IsConst;
166 bool IsCtor;
167 StorageClass SC;
170
171 // Argument placeholders, inspired by std::placeholder. These are the indices
172 // of arguments to forward to `callBuiltin` and other method builder methods.
173 // Additional special values are:
174 // Handle - refers to the resource handle.
175 // LastStmt - refers to the last statement in the method body; referencing
176 // LastStmt will remove the statement from the method body since
177 // it will be linked from the new expression being constructed.
178 enum class PlaceHolder {
179 _0,
180 _1,
181 _2,
182 _3,
183 _4,
184 _5,
185 Handle = 128,
186 CounterHandle,
187 LastStmt
188 };
189
190 Expr *convertPlaceholder(PlaceHolder PH);
191 Expr *convertPlaceholder(LocalVar &Var);
192 Expr *convertPlaceholder(Expr *E) { return E; }
193
194public:
196
198 QualType ReturnTy, bool IsConst = false,
199 bool IsCtor = false, StorageClass SC = SC_None)
200 : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
201 IsConst(IsConst), IsCtor(IsCtor), SC(SC) {}
202
204 QualType ReturnTy, bool IsConst = false,
205 bool IsCtor = false, StorageClass SC = SC_None);
207
209
212
213 BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
214 HLSLParamModifierAttr::Spelling Modifier =
215 HLSLParamModifierAttr::Keyword_in);
217 template <typename... Ts>
218 BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
219 QualType ReturnType, Ts &&...ArgSpecs);
220 template <typename TLHS, typename TRHS>
221 BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
222 template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
223
224 template <typename T>
226 template <typename ResourceT, typename ValueT>
227 BuiltinTypeMethodBuilder &setHandleFieldOnResource(ResourceT ResourceRecord,
228 ValueT HandleValue);
229 template <typename T>
232 template <typename ResourceT, typename ValueT>
234 setCounterHandleFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue);
235 template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
240
241private:
242 void createDecl();
243
244 // Makes sure the declaration is created; should be called before any
245 // statement added to the body or when access to 'this' is needed.
246 void ensureCompleteDecl() {
247 if (!Method)
248 createDecl();
249 }
250
251 template <typename ResourceT, typename ValueT>
252 BuiltinTypeMethodBuilder &setFieldOnResource(ResourceT ResourceRecord,
253 ValueT HandleValue,
254 FieldDecl *HandleField);
255};
256
260
263 QualType DefaultValue) {
264 assert(!Builder.Record->isCompleteDefinition() &&
265 "record is already complete");
266 ASTContext &AST = Builder.SemaRef.getASTContext();
267 unsigned Position = static_cast<unsigned>(Params.size());
269 AST, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(),
270 /* TemplateDepth */ 0, Position,
271 &AST.Idents.get(Name, tok::TokenKind::identifier),
272 /* Typename */ true,
273 /* ParameterPack */ false,
274 /* HasTypeConstraint*/ false);
275 if (!DefaultValue.isNull())
276 Decl->setDefaultArgument(AST,
277 Builder.SemaRef.getTrivialTemplateArgumentLoc(
278 DefaultValue, QualType(), SourceLocation()));
279
280 Params.emplace_back(Decl);
281 return *this;
282}
283
284// The concept specialization expression (CSE) constructed in
285// constructConceptSpecializationExpr is constructed so that it
286// matches the CSE that is constructed when parsing the below C++ code:
287//
288// template<typename T>
289// concept is_typed_resource_element_compatible =
290// __builtin_hlsl_typed_resource_element_compatible<T>
291//
292// template<typename element_type> requires
293// is_typed_resource_element_compatible<element_type>
294// struct RWBuffer {
295// element_type Val;
296// };
297//
298// int fn() {
299// RWBuffer<int> Buf;
300// }
301//
302// When dumping the AST and filtering for "RWBuffer", the resulting AST
303// structure is what we're trying to construct below, specifically the
304// CSE portion.
307 Sema &S, ConceptDecl *CD) {
308 ASTContext &Context = S.getASTContext();
309 SourceLocation Loc = Builder.Record->getBeginLoc();
310 DeclarationNameInfo DNI(CD->getDeclName(), Loc);
312 DeclContext *DC = Builder.Record->getDeclContext();
313 TemplateArgumentListInfo TALI(Loc, Loc);
314
315 // Assume that the concept decl has just one template parameter
316 // This parameter should have been added when CD was constructed
317 // in getTypedBufferConceptDecl
318 assert(CD->getTemplateParameters()->size() == 1 &&
319 "unexpected concept decl parameter count");
320 TemplateTypeParmDecl *ConceptTTPD =
321 dyn_cast<TemplateTypeParmDecl>(CD->getTemplateParameters()->getParam(0));
322
323 // this TemplateTypeParmDecl is the template for the resource, and is
324 // used to construct a template argumentthat will be used
325 // to construct the ImplicitConceptSpecializationDecl
327 Context, // AST context
328 Builder.Record->getDeclContext(), // DeclContext
330 /*D=*/0, // Depth in the template parameter list
331 /*P=*/0, // Position in the template parameter list
332 /*Id=*/nullptr, // Identifier for 'T'
333 /*Typename=*/true, // Indicates this is a 'typename' or 'class'
334 /*ParameterPack=*/false, // Not a parameter pack
335 /*HasTypeConstraint=*/false // Has no type constraint
336 );
337
338 T->setDeclContext(DC);
339
340 QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
341
342 // this is the 2nd template argument node, on which
343 // the concept constraint is actually being applied: 'element_type'
344 TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
345
346 QualType CSETType = Context.getTypeDeclType(T);
347
348 // this is the 1st template argument node, which represents
349 // the abstract type that a concept would refer to: 'T'
350 TemplateArgument CSETA = TemplateArgument(CSETType);
351
352 ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
354 Context, Builder.Record->getDeclContext(), Loc, {CSETA});
355
356 // Constraint satisfaction is used to construct the
357 // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
358 // located at the bottom of the sample AST above.
359 const ConstraintSatisfaction CS(CD, {ConceptTA});
362
363 TALI.addArgument(TAL);
364 const ASTTemplateArgumentListInfo *ATALI =
366
367 // In the concept reference, ATALI is what adds the extra
368 // TemplateArgument node underneath CSE
369 ConceptReference *CR =
370 ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
371
373 ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
374
375 return CSE;
376}
377
380 if (Params.empty())
381 return Builder;
382
383 ASTContext &AST = Builder.SemaRef.Context;
385 CD ? constructConceptSpecializationExpr(Builder.SemaRef, CD) : nullptr;
386 auto *ParamList = TemplateParameterList::Create(
389 AST, Builder.Record->getDeclContext(), SourceLocation(),
390 DeclarationName(Builder.Record->getIdentifier()), ParamList,
391 Builder.Record);
392
393 Builder.Record->setDescribedClassTemplate(Builder.Template);
394 Builder.Template->setImplicit(true);
395 Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
396
397 // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
398 // make visible.
399 Builder.Template->setPreviousDecl(Builder.PrevTemplate);
400 Builder.Record->getDeclContext()->addDecl(Builder.Template);
401 Params.clear();
402
403 return Builder;
404}
405
406Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
407 if (PH == PlaceHolder::Handle)
408 return getResourceHandleExpr();
409 if (PH == PlaceHolder::CounterHandle)
411
412 if (PH == PlaceHolder::LastStmt) {
413 assert(!StmtsList.empty() && "no statements in the list");
414 Stmt *LastStmt = StmtsList.pop_back_val();
415 assert(isa<ValueStmt>(LastStmt) && "last statement does not have a value");
416 return cast<ValueStmt>(LastStmt)->getExprStmt();
417 }
418
419 // All other placeholders are parameters (_N), and can be loaded as an
420 // LValue. It needs to be an LValue if the result expression will be used as
421 // the actual parameter for an out parameter. The dimension builtins are an
422 // example where this happens.
423 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
424 ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
425 return DeclRefExpr::Create(
426 AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
428 ParamDecl->getType().getNonReferenceType(), VK_LValue);
429}
430
431Expr *BuiltinTypeMethodBuilder::convertPlaceholder(LocalVar &Var) {
432 VarDecl *VD = Var.Decl;
433 assert(VD && "local variable is not declared");
434 return DeclRefExpr::Create(
435 VD->getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
436 false, DeclarationNameInfo(VD->getDeclName(), SourceLocation()),
437 VD->getType(), VK_LValue);
438}
439
441 StringRef NameStr,
442 QualType ReturnTy,
443 bool IsConst, bool IsCtor,
444 StorageClass SC)
445 : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
446 IsCtor(IsCtor), SC(SC) {
447
448 assert((!NameStr.empty() || IsCtor) && "method needs a name");
449 assert(((IsCtor && !IsConst) || !IsCtor) && "constructor cannot be const");
450
451 ASTContext &AST = DB.SemaRef.getASTContext();
452 if (IsCtor) {
454 AST.getCanonicalTagType(DB.Record));
455 } else {
456 const IdentifierInfo &II =
457 AST.Idents.get(NameStr, tok::TokenKind::identifier);
458 Name = DeclarationName(&II);
459 }
460}
461
464 HLSLParamModifierAttr::Spelling Modifier) {
465 assert(Method == nullptr && "Cannot add param, method already created");
466 const IdentifierInfo &II = DeclBuilder.SemaRef.getASTContext().Idents.get(
467 Name, tok::TokenKind::identifier);
468 Params.emplace_back(II, Ty, Modifier);
469 return *this;
470}
471
472void BuiltinTypeMethodBuilder::createDecl() {
473 assert(Method == nullptr && "Method or constructor is already created");
474
475 // create function prototype
476 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
477 SmallVector<QualType> ParamTypes;
478 SmallVector<FunctionType::ExtParameterInfo> ParamExtInfos(Params.size());
479 uint32_t ArgIndex = 0;
480
481 // Create function prototype.
482 bool UseParamExtInfo = false;
483 for (Param &MP : Params) {
484 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
485 UseParamExtInfo = true;
486 FunctionType::ExtParameterInfo &PI = ParamExtInfos[ArgIndex];
487 ParamExtInfos[ArgIndex] =
488 PI.withABI(convertParamModifierToParamABI(MP.Modifier));
489 if (!MP.Ty->isDependentType())
490 MP.Ty = getInoutParameterType(AST, MP.Ty);
491 }
492 ParamTypes.emplace_back(MP.Ty);
493 ++ArgIndex;
494 }
495
496 FunctionProtoType::ExtProtoInfo ExtInfo;
497 if (UseParamExtInfo)
498 ExtInfo.ExtParameterInfos = ParamExtInfos.data();
499 if (IsConst)
500 ExtInfo.TypeQuals.addConst();
501
502 QualType FuncTy = AST.getFunctionType(ReturnTy, ParamTypes, ExtInfo);
503
504 // Create method or constructor declaration.
505 auto *TSInfo = AST.getTrivialTypeSourceInfo(FuncTy, SourceLocation());
506 DeclarationNameInfo NameInfo = DeclarationNameInfo(Name, SourceLocation());
507 if (IsCtor)
509 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo,
510 ExplicitSpecifier(), false, /*IsInline=*/true, false,
512 else
513 Method = CXXMethodDecl::Create(
514 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo, SC,
515 false, true, ConstexprSpecKind::Unspecified, SourceLocation());
516
517 // Create params & set them to the method/constructor and function prototype.
519 unsigned CurScopeDepth = DeclBuilder.SemaRef.getCurScope()->getDepth();
520 auto FnProtoLoc =
521 Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
522 for (int I = 0, E = Params.size(); I != E; I++) {
523 Param &MP = Params[I];
524 ParmVarDecl *Parm = ParmVarDecl::Create(
525 AST, Method->getDeclContext(), SourceLocation(), SourceLocation(),
526 &MP.NameII, MP.Ty,
527 AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None,
528 nullptr);
529 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
530 auto *Mod =
531 HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
532 Parm->addAttr(Mod);
533 }
534 Parm->setScopeInfo(CurScopeDepth, I);
535 ParmDecls.push_back(Parm);
536 FnProtoLoc.setParam(I, Parm);
537 }
538 Method->setParams({ParmDecls});
539}
540
542 ensureCompleteDecl();
543
544 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
546 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
547 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
548 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
549 HandleField->getType(), VK_LValue,
551}
552
554 ensureCompleteDecl();
555
556 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
558 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
559 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
560 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
561 HandleField->getType(), VK_LValue,
563}
564
567 ensureCompleteDecl();
568
569 assert(Var.Decl == nullptr && "local variable is already declared");
570
571 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
572 Var.Decl = VarDecl::Create(
573 AST, Method, SourceLocation(), SourceLocation(),
574 &AST.Idents.get(Var.Name, tok::TokenKind::identifier), Var.Ty,
576 DeclStmt *DS = new (AST) clang::DeclStmt(DeclGroupRef(Var.Decl),
578 StmtsList.push_back(DS);
579 return *this;
580}
581
583 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
585 AST, SourceLocation(), Method->getFunctionObjectParameterType(),
586 /*IsImplicit=*/true);
587 StmtsList.push_back(ThisExpr);
588 return *this;
589}
590
591template <typename... Ts>
594 QualType ReturnType, Ts &&...ArgSpecs) {
595 ensureCompleteDecl();
596
597 std::array<Expr *, sizeof...(ArgSpecs)> Args{
598 convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
599
600 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
601 FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
603 AST, NestedNameSpecifierLoc(), SourceLocation(), FD, false,
605
606 ExprResult Call = DeclBuilder.SemaRef.BuildCallExpr(
607 /*Scope=*/nullptr, DRE, SourceLocation(),
608 MultiExprArg(Args.data(), Args.size()), SourceLocation());
609 assert(!Call.isInvalid() && "Call to builtin cannot fail!");
610 Expr *E = Call.get();
611
612 if (!ReturnType.isNull() &&
613 !AST.hasSameUnqualifiedType(ReturnType, E->getType())) {
614 ExprResult CastResult = DeclBuilder.SemaRef.BuildCStyleCastExpr(
615 SourceLocation(), AST.getTrivialTypeSourceInfo(ReturnType),
616 SourceLocation(), E);
617 assert(!CastResult.isInvalid() && "Cast cannot fail!");
618 E = CastResult.get();
619 }
620
621 StmtsList.push_back(E);
622 return *this;
623}
624
625template <typename TLHS, typename TRHS>
627 Expr *LHSExpr = convertPlaceholder(LHS);
628 Expr *RHSExpr = convertPlaceholder(RHS);
629 Stmt *AssignStmt = BinaryOperator::Create(
630 DeclBuilder.SemaRef.getASTContext(), LHSExpr, RHSExpr, BO_Assign,
633 StmtsList.push_back(AssignStmt);
634 return *this;
635}
636
637template <typename T>
639 Expr *PtrExpr = convertPlaceholder(Ptr);
640 Expr *Deref =
641 UnaryOperator::Create(DeclBuilder.SemaRef.getASTContext(), PtrExpr,
642 UO_Deref, PtrExpr->getType()->getPointeeType(),
644 /*CanOverflow=*/false, FPOptionsOverride());
645 StmtsList.push_back(Deref);
646 return *this;
647}
648
649template <typename T>
652 ensureCompleteDecl();
653
654 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
655 auto *ResourceTypeDecl = ResourceExpr->getType()->getAsCXXRecordDecl();
656
657 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
658 FieldDecl *HandleField = nullptr;
659
660 if (ResourceTypeDecl == DeclBuilder.Record)
661 HandleField = DeclBuilder.getResourceHandleField();
662 else {
663 IdentifierInfo &II = AST.Idents.get("__handle");
664 for (auto *Decl : ResourceTypeDecl->lookup(&II)) {
665 if ((HandleField = dyn_cast<FieldDecl>(Decl)))
666 break;
667 }
668 assert(HandleField && "Resource handle field not found");
669 }
670
672 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
674 StmtsList.push_back(HandleExpr);
675 return *this;
676}
677
678template <typename ResourceT, typename ValueT>
681 ValueT HandleValue) {
682 return setFieldOnResource(ResourceRecord, HandleValue,
683 DeclBuilder.getResourceHandleField());
684}
685
686template <typename ResourceT, typename ValueT>
689 ResourceT ResourceRecord, ValueT HandleValue) {
690 return setFieldOnResource(ResourceRecord, HandleValue,
691 DeclBuilder.getResourceCounterHandleField());
692}
693
694template <typename ResourceT, typename ValueT>
695BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::setFieldOnResource(
696 ResourceT ResourceRecord, ValueT HandleValue, FieldDecl *HandleField) {
697 ensureCompleteDecl();
698
699 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
700 assert(ResourceExpr->getType()->getAsCXXRecordDecl() ==
701 HandleField->getParent() &&
702 "Getting the field from the wrong resource type.");
703
704 Expr *HandleValueExpr = convertPlaceholder(HandleValue);
705
706 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
707 MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
708 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
710 Stmt *AssignStmt = BinaryOperator::Create(
711 DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr,
712 BO_Assign, HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
714 StmtsList.push_back(AssignStmt);
715 return *this;
716}
717
718template <typename T>
719BuiltinTypeMethodBuilder &
721 ensureCompleteDecl();
722
723 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
724 assert(ResourceExpr->getType()->getAsCXXRecordDecl() == DeclBuilder.Record &&
725 "Getting the field from the wrong resource type.");
726
727 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
728 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
730 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
732 StmtsList.push_back(HandleExpr);
733 return *this;
734}
735
736template <typename T>
738 ensureCompleteDecl();
739
740 Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
741 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
742
743 QualType Ty = ReturnValueExpr->getType();
744 if (Ty->isRecordType()) {
745 // For record types, create a call to copy constructor to ensure proper copy
746 // semantics.
747 auto *ICE =
748 ImplicitCastExpr::Create(AST, Ty.withConst(), CK_NoOp, ReturnValueExpr,
749 nullptr, VK_XValue, FPOptionsOverride());
750 CXXConstructorDecl *CD = lookupCopyConstructor(Ty);
751 assert(CD && "no copy constructor found");
752 ReturnValueExpr = CXXConstructExpr::Create(
753 AST, Ty, SourceLocation(), CD, /*Elidable=*/false, {ICE},
754 /*HadMultipleCandidates=*/false, /*ListInitialization=*/false,
755 /*StdInitListInitialization=*/false,
756 /*ZeroInitListInitialization=*/false, CXXConstructionKind::Complete,
757 SourceRange());
758 }
759 StmtsList.push_back(
760 ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
761 return *this;
762}
763
765 assert(!DeclBuilder.Record->isCompleteDefinition() &&
766 "record is already complete");
767
768 ensureCompleteDecl();
769
770 if (!Method->hasBody()) {
771 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
772 assert((ReturnTy == AST.VoidTy || !StmtsList.empty()) &&
773 "nothing to return from non-void method");
774 if (ReturnTy != AST.VoidTy) {
775 if (Expr *LastExpr = dyn_cast<Expr>(StmtsList.back())) {
776 assert(AST.hasSameUnqualifiedType(LastExpr->getType(),
777 ReturnTy.getNonReferenceType()) &&
778 "Return type of the last statement must match the return type "
779 "of the method");
780 if (!isa<ReturnStmt>(LastExpr)) {
781 StmtsList.pop_back();
782 StmtsList.push_back(
783 ReturnStmt::Create(AST, SourceLocation(), LastExpr, nullptr));
784 }
785 }
786 }
787
788 Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
790 Method->setLexicalDeclContext(DeclBuilder.Record);
791 Method->setAccess(AS_public);
792 Method->addAttr(AlwaysInlineAttr::CreateImplicit(
793 AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
794 DeclBuilder.Record->addDecl(Method);
795 }
796 return DeclBuilder;
797}
798
800 : SemaRef(SemaRef), Record(R) {
801 Record->startDefinition();
802 Template = Record->getDescribedClassTemplate();
803}
804
806 NamespaceDecl *Namespace,
807 StringRef Name)
808 : SemaRef(SemaRef), HLSLNamespace(Namespace) {
809 ASTContext &AST = SemaRef.getASTContext();
810 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
811
813 CXXRecordDecl *PrevDecl = nullptr;
814 if (SemaRef.LookupQualifiedName(Result, HLSLNamespace)) {
815 // Declaration already exists (from precompiled headers)
816 NamedDecl *Found = Result.getFoundDecl();
817 if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
818 PrevDecl = TD->getTemplatedDecl();
819 PrevTemplate = TD;
820 } else
821 PrevDecl = dyn_cast<CXXRecordDecl>(Found);
822 assert(PrevDecl && "Unexpected lookup result type.");
823 }
824
825 if (PrevDecl && PrevDecl->isCompleteDefinition()) {
826 Record = PrevDecl;
827 Template = PrevTemplate;
828 return;
829 }
830
831 Record =
832 CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
833 SourceLocation(), SourceLocation(), &II, PrevDecl);
834 Record->setImplicit(true);
835 Record->setLexicalDeclContext(HLSLNamespace);
836 Record->setHasExternalLexicalStorage();
837
838 // Don't let anyone derive from built-in types.
839 Record->addAttr(
840 FinalAttr::CreateImplicit(AST, SourceRange(), FinalAttr::Keyword_final));
841}
842
844 if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
845 HLSLNamespace->addDecl(Record);
846}
847
851 AccessSpecifier Access) {
852 assert(!Record->isCompleteDefinition() && "record is already complete");
853 assert(Record->isBeingDefined() &&
854 "Definition must be started before adding members!");
855 ASTContext &AST = Record->getASTContext();
856
857 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
858 TypeSourceInfo *MemTySource =
860 auto *Field = FieldDecl::Create(
861 AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
862 nullptr, false, InClassInitStyle::ICIS_NoInit);
863 Field->setAccess(Access);
864 Field->setImplicit(true);
865 for (Attr *A : Attrs) {
866 if (A)
867 Field->addAttr(A);
868 }
869
870 Record->addDecl(Field);
871 Fields[Name] = Field;
872 return *this;
873}
874
876BuiltinTypeDeclBuilder::addBufferHandles(ResourceClass RC, bool IsROV,
877 bool RawBuffer, bool HasCounter,
878 AccessSpecifier Access) {
879 addHandleMember(RC, ResourceDimension::Unknown, IsROV, RawBuffer, Access);
880 if (HasCounter)
881 addCounterHandleMember(RC, IsROV, RawBuffer, Access);
882 return *this;
883}
884
886BuiltinTypeDeclBuilder::addTextureHandle(ResourceClass RC, bool IsROV,
887 ResourceDimension RD,
888 AccessSpecifier Access) {
889 addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, Access);
890 return *this;
891}
892
894 addHandleMember(ResourceClass::Sampler, ResourceDimension::Unknown,
895 /*IsROV=*/false, /*RawBuffer=*/false);
896 return *this;
897}
898
900BuiltinTypeDeclBuilder::addHandleMember(ResourceClass RC, ResourceDimension RD,
901 bool IsROV, bool RawBuffer,
902 AccessSpecifier Access) {
903 return addResourceMember("__handle", RC, RD, IsROV, RawBuffer,
904 /*IsCounter=*/false, Access);
905}
906
907BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
908 ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
909 return addResourceMember("__counter_handle", RC, ResourceDimension::Unknown,
910 IsROV, RawBuffer,
911 /*IsCounter=*/true, Access);
912}
913
914BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember(
915 StringRef MemberName, ResourceClass RC, ResourceDimension RD, bool IsROV,
916 bool RawBuffer, bool IsCounter, AccessSpecifier Access) {
917 assert(!Record->isCompleteDefinition() && "record is already complete");
918
919 ASTContext &Ctx = SemaRef.getASTContext();
920 TypeSourceInfo *ElementTypeInfo =
921 Ctx.getTrivialTypeSourceInfo(getHandleElementType(), SourceLocation());
922
923 // add handle member with resource type attributes
924 QualType AttributedResTy = QualType();
926 HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
927 IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
928 RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
929 RD != ResourceDimension::Unknown
930 ? HLSLResourceDimensionAttr::CreateImplicit(Ctx, RD)
931 : nullptr,
932 ElementTypeInfo && RC != ResourceClass::Sampler
933 ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
934 : nullptr};
935 if (IsCounter)
936 Attrs.push_back(HLSLIsCounterAttr::CreateImplicit(Ctx));
937
938 if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
939 AttributedResTy))
940 addMemberVariable(MemberName, AttributedResTy, {}, Access);
941 return *this;
942}
943
944// Adds default constructor to the resource class:
945// Resource::Resource()
947 assert(!Record->isCompleteDefinition() && "record is already complete");
948
949 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
950 QualType HandleType = getResourceHandleField()->getType();
951 return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
952 false, true)
953 .callBuiltin("__builtin_hlsl_resource_uninitializedhandle", HandleType,
954 PH::Handle)
955 .assign(PH::Handle, PH::LastStmt)
956 .finalize();
957}
958
961 if (HasCounter) {
962 addCreateFromBindingWithImplicitCounter();
963 addCreateFromImplicitBindingWithImplicitCounter();
964 } else {
965 addCreateFromBinding();
966 addCreateFromImplicitBinding();
967 }
968 return *this;
969}
970
971// Adds static method that initializes resource from binding:
972//
973// static Resource<T> __createFromBinding(unsigned registerNo,
974// unsigned spaceNo, int range,
975// unsigned index, const char *name) {
976// Resource<T> tmp;
977// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
978// tmp.__handle, registerNo, spaceNo,
979// range, index, name);
980// return tmp;
981// }
982BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
983 assert(!Record->isCompleteDefinition() && "record is already complete");
984
985 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
986 ASTContext &AST = SemaRef.getASTContext();
987 QualType HandleType = getResourceHandleField()->getType();
989 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
990
991 return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
992 false, false, SC_Static)
993 .addParam("registerNo", AST.UnsignedIntTy)
994 .addParam("spaceNo", AST.UnsignedIntTy)
995 .addParam("range", AST.IntTy)
996 .addParam("index", AST.UnsignedIntTy)
997 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
998 .declareLocalVar(TmpVar)
999 .accessHandleFieldOnResource(TmpVar)
1000 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1001 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1002 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1003 .returnValue(TmpVar)
1004 .finalize();
1005}
1006
1007// Adds static method that initializes resource from binding:
1008//
1009// static Resource<T> __createFromImplicitBinding(unsigned orderId,
1010// unsigned spaceNo, int range,
1011// unsigned index,
1012// const char *name) {
1013// Resource<T> tmp;
1014// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1015// tmp.__handle, spaceNo,
1016// range, index, orderId, name);
1017// return tmp;
1018// }
1019BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
1020 assert(!Record->isCompleteDefinition() && "record is already complete");
1021
1022 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1023 ASTContext &AST = SemaRef.getASTContext();
1024 QualType HandleType = getResourceHandleField()->getType();
1025 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1026 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1027
1028 return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
1029 RecordType, false, false, SC_Static)
1030 .addParam("orderId", AST.UnsignedIntTy)
1031 .addParam("spaceNo", AST.UnsignedIntTy)
1032 .addParam("range", AST.IntTy)
1033 .addParam("index", AST.UnsignedIntTy)
1034 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1035 .declareLocalVar(TmpVar)
1036 .accessHandleFieldOnResource(TmpVar)
1037 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1038 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1039 PH::_4)
1040 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1041 .returnValue(TmpVar)
1042 .finalize();
1043}
1044
1045// Adds static method that initializes resource from binding:
1046//
1047// static Resource<T>
1048// __createFromBindingWithImplicitCounter(unsigned registerNo,
1049// unsigned spaceNo, int range,
1050// unsigned index, const char *name,
1051// unsigned counterOrderId) {
1052// Resource<T> tmp;
1053// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1054// tmp.__handle, registerNo, spaceNo, range, index, name);
1055// tmp.__counter_handle =
1056// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1057// tmp.__handle, counterOrderId, spaceNo);
1058// return tmp;
1059// }
1061BuiltinTypeDeclBuilder::addCreateFromBindingWithImplicitCounter() {
1062 assert(!Record->isCompleteDefinition() && "record is already complete");
1063
1064 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1065 ASTContext &AST = SemaRef.getASTContext();
1066 QualType HandleType = getResourceHandleField()->getType();
1067 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1068 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1069 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1070
1071 return BuiltinTypeMethodBuilder(*this,
1072 "__createFromBindingWithImplicitCounter",
1073 RecordType, false, false, SC_Static)
1074 .addParam("registerNo", AST.UnsignedIntTy)
1075 .addParam("spaceNo", AST.UnsignedIntTy)
1076 .addParam("range", AST.IntTy)
1077 .addParam("index", AST.UnsignedIntTy)
1078 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1079 .addParam("counterOrderId", AST.UnsignedIntTy)
1080 .declareLocalVar(TmpVar)
1081 .accessHandleFieldOnResource(TmpVar)
1082 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1083 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1084 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1085 .accessHandleFieldOnResource(TmpVar)
1086 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1087 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1088 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1089 .returnValue(TmpVar)
1090 .finalize();
1091}
1092
1093// Adds static method that initializes resource from binding:
1094//
1095// static Resource<T>
1096// __createFromImplicitBindingWithImplicitCounter(unsigned orderId,
1097// unsigned spaceNo, int range,
1098// unsigned index,
1099// const char *name,
1100// unsigned counterOrderId) {
1101// Resource<T> tmp;
1102// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1103// tmp.__handle, orderId, spaceNo, range, index, name);
1104// tmp.__counter_handle =
1105// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1106// tmp.__handle, counterOrderId, spaceNo);
1107// return tmp;
1108// }
1110BuiltinTypeDeclBuilder::addCreateFromImplicitBindingWithImplicitCounter() {
1111 assert(!Record->isCompleteDefinition() && "record is already complete");
1112
1113 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1114 ASTContext &AST = SemaRef.getASTContext();
1115 QualType HandleType = getResourceHandleField()->getType();
1116 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1117 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1118 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1119
1121 *this, "__createFromImplicitBindingWithImplicitCounter",
1122 RecordType, false, false, SC_Static)
1123 .addParam("orderId", AST.UnsignedIntTy)
1124 .addParam("spaceNo", AST.UnsignedIntTy)
1125 .addParam("range", AST.IntTy)
1126 .addParam("index", AST.UnsignedIntTy)
1127 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1128 .addParam("counterOrderId", AST.UnsignedIntTy)
1129 .declareLocalVar(TmpVar)
1130 .accessHandleFieldOnResource(TmpVar)
1131 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1132 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1133 PH::_4)
1134 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1135 .accessHandleFieldOnResource(TmpVar)
1136 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1137 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1138 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1139 .returnValue(TmpVar)
1140 .finalize();
1141}
1142
1144 assert(!Record->isCompleteDefinition() && "record is already complete");
1145
1146 ASTContext &AST = SemaRef.getASTContext();
1147 QualType RecordType = AST.getCanonicalTagType(Record);
1148 QualType ConstRecordType = RecordType.withConst();
1149 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1150
1151 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1152
1153 BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy,
1154 /*IsConst=*/false, /*IsCtor=*/true);
1155 MMB.addParam("other", ConstRecordRefType)
1157 .assign(PH::Handle, PH::LastStmt);
1158
1159 if (getResourceCounterHandleField())
1160 MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
1161 PH::LastStmt);
1162
1163 return MMB.finalize();
1164}
1165
1167 assert(!Record->isCompleteDefinition() && "record is already complete");
1168
1169 ASTContext &AST = SemaRef.getASTContext();
1170 QualType RecordType = AST.getCanonicalTagType(Record);
1171 QualType ConstRecordType = RecordType.withConst();
1172 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1173 QualType RecordRefType = AST.getLValueReferenceType(RecordType);
1174
1175 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1177 BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType);
1178 MMB.addParam("other", ConstRecordRefType)
1180 .assign(PH::Handle, PH::LastStmt);
1181
1182 if (getResourceCounterHandleField())
1183 MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
1184 PH::LastStmt);
1185
1186 return MMB.returnThis().finalize();
1187}
1188
1190 ASTContext &AST = Record->getASTContext();
1191 DeclarationName Subscript =
1192 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1193
1194 addHandleAccessFunction(Subscript, /*IsConst=*/true, /*IsRef=*/true);
1195 if (getResourceAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV)
1196 addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true);
1197
1198 return *this;
1199}
1200
1202 assert(!Record->isCompleteDefinition() && "record is already complete");
1203
1204 ASTContext &AST = Record->getASTContext();
1205 IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
1206 DeclarationName Load(&II);
1207 // TODO: We also need versions with status for CheckAccessFullyMapped.
1208 addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false);
1209 addLoadWithStatusFunction(Load, /*IsConst=*/false);
1210
1211 return *this;
1212}
1213
1216 assert(!Record->isCompleteDefinition() && "record is already complete");
1217
1218 ASTContext &AST = Record->getASTContext();
1219 QualType ReturnType = getFirstTemplateTypeParam();
1220
1221 QualType SamplerStateType =
1222 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1223
1224 uint32_t VecSize = getResourceDimensions(Dim);
1225
1226 QualType FloatTy = AST.FloatTy;
1227 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1228
1229 QualType IntTy = AST.IntTy;
1230 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1231
1232 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1233
1234 // T Sample(SamplerState s, float2 location)
1235 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1236 .addParam("Sampler", SamplerStateType)
1237 .addParam("Location", Float2Ty)
1238 .accessHandleFieldOnResource(PH::_0)
1239 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1240 PH::LastStmt, PH::_1)
1241 .returnValue(PH::LastStmt)
1242 .finalize();
1243
1244 // T Sample(SamplerState s, float2 location, int2 offset)
1245 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1246 .addParam("Sampler", SamplerStateType)
1247 .addParam("Location", Float2Ty)
1248 .addParam("Offset", Int2Ty)
1249 .accessHandleFieldOnResource(PH::_0)
1250 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1251 PH::LastStmt, PH::_1, PH::_2)
1252 .returnValue(PH::LastStmt)
1253 .finalize();
1254
1255 // T Sample(SamplerState s, float2 location, int2 offset, float clamp)
1256 return BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1257 .addParam("Sampler", SamplerStateType)
1258 .addParam("Location", Float2Ty)
1259 .addParam("Offset", Int2Ty)
1260 .addParam("Clamp", FloatTy)
1261 .accessHandleFieldOnResource(PH::_0)
1262 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1263 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1264 .returnValue(PH::LastStmt)
1265 .finalize();
1266}
1267
1268FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
1269 auto I = Fields.find("__handle");
1270 assert(I != Fields.end() &&
1271 I->second->getType()->isHLSLAttributedResourceType() &&
1272 "record does not have resource handle field");
1273 return I->second;
1274}
1275
1276FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField() const {
1277 auto I = Fields.find("__counter_handle");
1278 if (I == Fields.end() ||
1279 !I->second->getType()->isHLSLAttributedResourceType())
1280 return nullptr;
1281 return I->second;
1282}
1283
1284QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
1285 assert(Template && "record it not a template");
1286 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
1287 Template->getTemplateParameters()->getParam(0))) {
1288 return QualType(TTD->getTypeForDecl(), 0);
1289 }
1290 return QualType();
1291}
1292
1293QualType BuiltinTypeDeclBuilder::getHandleElementType() {
1294 if (Template)
1295 return getFirstTemplateTypeParam();
1296 // TODO: Should we default to VoidTy? Using `i8` is arguably ambiguous.
1297 return SemaRef.getASTContext().Char8Ty;
1298}
1299
1300HLSLAttributedResourceType::Attributes
1301BuiltinTypeDeclBuilder::getResourceAttrs() const {
1302 QualType HandleType = getResourceHandleField()->getType();
1303 return cast<HLSLAttributedResourceType>(HandleType)->getAttrs();
1304}
1305
1307 assert(!Record->isCompleteDefinition() && "record is already complete");
1308 assert(Record->isBeingDefined() &&
1309 "Definition must be started before completing it.");
1310
1311 Record->completeDefinition();
1312 return *this;
1313}
1314
1315Expr *BuiltinTypeDeclBuilder::getConstantIntExpr(int value) {
1316 ASTContext &AST = SemaRef.getASTContext();
1318 AST, llvm::APInt(AST.getTypeSize(AST.IntTy), value, true), AST.IntTy,
1319 SourceLocation());
1320}
1321
1324 ConceptDecl *CD = nullptr) {
1325 if (Record->isCompleteDefinition()) {
1326 assert(Template && "existing record it not a template");
1327 assert(Template->getTemplateParameters()->size() == Names.size() &&
1328 "template param count mismatch");
1329 return *this;
1330 }
1331
1333 for (StringRef Name : Names)
1334 Builder.addTypeParameter(Name);
1335 return Builder.finalizeTemplateArgs(CD);
1336}
1337
1339 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1340 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
1341 return BuiltinTypeMethodBuilder(*this, "IncrementCounter", UnsignedIntTy)
1342 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
1343 PH::CounterHandle, getConstantIntExpr(1))
1344 .finalize();
1345}
1346
1348 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1349 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
1350 return BuiltinTypeMethodBuilder(*this, "DecrementCounter", UnsignedIntTy)
1351 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
1352 PH::CounterHandle, getConstantIntExpr(-1))
1353 .finalize();
1354}
1355
1358 bool IsConst) {
1359 assert(!Record->isCompleteDefinition() && "record is already complete");
1360 ASTContext &AST = SemaRef.getASTContext();
1361 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1362
1363 QualType ReturnTy = getHandleElementType();
1364 return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, IsConst)
1365 .addParam("Index", AST.UnsignedIntTy)
1366 .addParam("Status", AST.UnsignedIntTy, HLSLParamModifierAttr::Keyword_out)
1367 .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy,
1368 PH::Handle, PH::_0, PH::_1)
1369 .finalize();
1370}
1371
1374 bool IsConst, bool IsRef) {
1375 assert(!Record->isCompleteDefinition() && "record is already complete");
1376 ASTContext &AST = SemaRef.getASTContext();
1377 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1378
1379 QualType ElemTy = getHandleElementType();
1380 QualType AddrSpaceElemTy =
1382 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
1383 QualType ReturnTy;
1384
1385 if (IsRef) {
1386 ReturnTy = AddrSpaceElemTy;
1387 if (IsConst)
1388 ReturnTy.addConst();
1389 ReturnTy = AST.getLValueReferenceType(ReturnTy);
1390 } else {
1391 ReturnTy = ElemTy;
1392 if (IsConst)
1393 ReturnTy.addConst();
1394 }
1395
1396 return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, IsConst)
1397 .addParam("Index", AST.UnsignedIntTy)
1398 .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
1399 PH::_0)
1400 .dereference(PH::LastStmt)
1401 .finalize();
1402}
1403
1405 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1406 ASTContext &AST = SemaRef.getASTContext();
1407 QualType ElemTy = getHandleElementType();
1408 QualType AddrSpaceElemTy =
1410 return BuiltinTypeMethodBuilder(*this, "Append", AST.VoidTy)
1411 .addParam("value", ElemTy)
1412 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
1413 PH::CounterHandle, getConstantIntExpr(1))
1414 .callBuiltin("__builtin_hlsl_resource_getpointer",
1415 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
1416 PH::LastStmt)
1417 .dereference(PH::LastStmt)
1418 .assign(PH::LastStmt, PH::_0)
1419 .finalize();
1420}
1421
1423 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1424 ASTContext &AST = SemaRef.getASTContext();
1425 QualType ElemTy = getHandleElementType();
1426 QualType AddrSpaceElemTy =
1428 return BuiltinTypeMethodBuilder(*this, "Consume", ElemTy)
1429 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
1430 PH::CounterHandle, getConstantIntExpr(-1))
1431 .callBuiltin("__builtin_hlsl_resource_getpointer",
1432 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
1433 PH::LastStmt)
1434 .dereference(PH::LastStmt)
1435 .finalize();
1436}
1437
1440 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1441 ASTContext &AST = SemaRef.getASTContext();
1442 QualType UIntTy = AST.UnsignedIntTy;
1443
1444 QualType HandleTy = getResourceHandleField()->getType();
1445 auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr());
1446
1447 // Structured buffers except {RW}ByteAddressBuffer have overload
1448 // GetDimensions(out uint numStructs, out uint stride).
1449 if (AttrResTy->getAttrs().RawBuffer &&
1450 AttrResTy->getContainedType() != AST.Char8Ty) {
1451 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
1452 .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out)
1453 .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out)
1454 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
1455 PH::Handle, PH::_0)
1456 .callBuiltin("__builtin_hlsl_resource_getstride", QualType(),
1457 PH::Handle, PH::_1)
1458 .finalize();
1459 }
1460
1461 // Typed buffers and {RW}ByteAddressBuffer have overload
1462 // GetDimensions(out uint dim).
1463 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
1464 .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out)
1465 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
1466 PH::Handle, PH::_0)
1467 .finalize();
1468}
1469
1470} // namespace hlsl
1471} // 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.
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:220
DeclarationNameTable DeclarationNames
Definition ASTContext.h:794
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.
IdentifierTable & Idents
Definition ASTContext.h:790
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:4982
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:1154
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:394
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:487
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1623
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.
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
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3396
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:4700
Represents a function declaration or definition.
Definition Decl.h:2000
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2211
Interesting information about a specific parameter that can't simply be reflected in parameter's type...
Definition TypeBase.h:4491
ExtParameterInfo withABI(ParameterABI kind) const
Definition TypeBase.h:4505
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:2072
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:974
Represents the results of name lookup.
Definition Lookup.h:147
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3364
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:3425
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
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:2957
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
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8302
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:8487
static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
Create a return statement.
Definition Stmt.cpp:1285
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:856
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:1121
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9357
@ LookupTagName
Tag name lookup, which finds the names of enums, classes, structs, and unions.
Definition Sema.h:9360
ASTContext & getASTContext() const
Definition Sema.h:927
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:3815
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:8273
The base class of the type hierarchy.
Definition TypeBase.h:1833
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:753
bool isRecordType() const
Definition TypeBase.h:8666
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:5039
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:2162
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 & addLoadWithStatusFunction(DeclarationName &Name, bool IsConst)
BuiltinTypeDeclBuilder & addHandleAccessFunction(DeclarationName &Name, bool IsConst, bool IsRef)
BuiltinTypeDeclBuilder & addGetDimensionsMethodForBuffer()
BuiltinTypeDeclBuilder & addBufferHandles(ResourceClass RC, bool IsROV, bool RawBuffer, bool HasCounter, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addTextureHandle(ResourceClass RC, bool IsROV, ResourceDimension RD, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addSampleMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addStaticInitializationFunctions(bool HasCounter)
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
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
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ 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...
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)