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"
21#include "clang/AST/Expr.h"
23#include "clang/AST/Stmt.h"
24#include "clang/AST/Type.h"
27#include "clang/Sema/Lookup.h"
28#include "clang/Sema/Sema.h"
29#include "clang/Sema/SemaHLSL.h"
30#include "llvm/ADT/SmallVector.h"
31
32using namespace llvm::hlsl;
33
34namespace clang {
35
36namespace hlsl {
37
38namespace {
39
40static FunctionDecl *lookupBuiltinFunction(Sema &S, StringRef Name) {
41 IdentifierInfo &II =
42 S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
43 DeclarationNameInfo NameInfo =
44 DeclarationNameInfo(DeclarationName(&II), SourceLocation());
45 LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
46 // AllowBuiltinCreation is false but LookupDirect will create
47 // the builtin when searching the global scope anyways...
48 S.LookupName(R, S.getCurScope());
49 // FIXME: If the builtin function was user-declared in global scope,
50 // this assert *will* fail. Should this call LookupBuiltin instead?
51 assert(R.isSingleResult() &&
52 "Since this is a builtin it should always resolve!");
53 return cast<FunctionDecl>(R.getFoundDecl());
54}
55
56static QualType lookupBuiltinType(Sema &S, StringRef Name, DeclContext *DC) {
57 IdentifierInfo &II =
58 S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
59 LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
60 S.LookupQualifiedName(Result, DC);
61 assert(!Result.empty() && "Builtin type not found");
62 QualType Ty =
63 S.getASTContext().getTypeDeclType(Result.getAsSingle<TypeDecl>());
64 S.RequireCompleteType(SourceLocation(), Ty,
65 diag::err_tentative_def_incomplete_type);
66 return Ty;
67}
68
69CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
70 assert(ResTy->isRecordType() && "not a CXXRecord type");
71 for (auto *CD : ResTy->getAsCXXRecordDecl()->ctors())
72 if (CD->isCopyConstructor())
73 return CD;
74 return nullptr;
75}
76
78convertParamModifierToParamABI(HLSLParamModifierAttr::Spelling Modifier) {
79 assert(Modifier != HLSLParamModifierAttr::Spelling::Keyword_in &&
80 "HLSL 'in' parameters modifier cannot be converted to ParameterABI");
81 switch (Modifier) {
82 case HLSLParamModifierAttr::Spelling::Keyword_out:
84 case HLSLParamModifierAttr::Spelling::Keyword_inout:
86 default:
87 llvm_unreachable("Invalid HLSL parameter modifier");
88 }
89}
90
91QualType getInoutParameterType(ASTContext &AST, QualType Ty) {
92 assert(!Ty->isReferenceType() &&
93 "Pointer and reference types cannot be inout or out parameters");
94 Ty = AST.getLValueReferenceType(Ty);
95 Ty.addRestrict();
96 return Ty;
97}
98
99} // namespace
100
101// Builder for template arguments of builtin types. Used internally
102// by BuiltinTypeDeclBuilder.
118
119// Builder for methods or constructors of builtin types. Allows creating methods
120// or constructors of builtin types using the builder pattern like this:
121//
122// BuiltinTypeMethodBuilder(RecordBuilder, "MethodName", ReturnType)
123// .addParam("param_name", Type, InOutModifier)
124// .callBuiltin("builtin_name", BuiltinParams...)
125// .finalize();
126//
127// The builder needs to have all of the parameters before it can create
128// a CXXMethodDecl or CXXConstructorDecl. It collects them in addParam calls and
129// when a first method that builds the body is called or when access to 'this`
130// is needed it creates the CXXMethodDecl/CXXConstructorDecl and ParmVarDecls
131// instances. These can then be referenced from the body building methods.
132// Destructor or an explicit call to finalize() will complete the method
133// definition.
134//
135// The callBuiltin helper method accepts constants via `Expr *` or placeholder
136// value arguments to indicate which function arguments to forward to the
137// builtin.
138//
139// If the method that is being built has a non-void return type the
140// finalize() will create a return statement with the value of the last
141// statement (unless the last statement is already a ReturnStmt or the return
142// value is void).
144private:
145 struct Param {
146 const IdentifierInfo &NameII;
147 QualType Ty;
148 HLSLParamModifierAttr::Spelling Modifier;
149 Param(const IdentifierInfo &NameII, QualType Ty,
150 HLSLParamModifierAttr::Spelling Modifier)
151 : NameII(NameII), Ty(Ty), Modifier(Modifier) {}
152 };
153
154 struct LocalVar {
155 StringRef Name;
156 QualType Ty;
157 VarDecl *Decl;
158 LocalVar(StringRef Name, QualType Ty) : Name(Name), Ty(Ty), Decl(nullptr) {}
159 };
160
161 BuiltinTypeDeclBuilder &DeclBuilder;
162 DeclarationName Name;
163 QualType ReturnTy;
164 // method or constructor declaration
165 // (CXXConstructorDecl derives from CXXMethodDecl)
166 CXXMethodDecl *Method;
167 bool IsConst;
168 bool IsCtor;
169 StorageClass SC;
172 TemplateParameterList *TemplateParams = nullptr;
173 llvm::SmallVector<NamedDecl *> TemplateParamDecls;
174
175 // Argument placeholders, inspired by std::placeholder. These are the indices
176 // of arguments to forward to `callBuiltin` and other method builder methods.
177 // Additional special values are:
178 // Handle - refers to the resource handle.
179 // LastStmt - refers to the last statement in the method body; referencing
180 // LastStmt will remove the statement from the method body since
181 // it will be linked from the new expression being constructed.
182 enum class PlaceHolder {
183 _0,
184 _1,
185 _2,
186 _3,
187 _4,
188 _5,
189 Handle = 128,
190 CounterHandle,
191 This,
192 LastStmt
193 };
194
195 Expr *convertPlaceholder(PlaceHolder PH);
196 Expr *convertPlaceholder(LocalVar &Var);
197 Expr *convertPlaceholder(Expr *E) { return E; }
198 // Converts a QualType to an Expr that carries type information to builtins.
199 Expr *convertPlaceholder(QualType Ty);
200
201public:
203
205 QualType ReturnTy, bool IsConst = false,
206 bool IsCtor = false, StorageClass SC = SC_None)
207 : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
208 IsConst(IsConst), IsCtor(IsCtor), SC(SC) {}
209
211 QualType ReturnTy, bool IsConst = false,
212 bool IsCtor = false, StorageClass SC = SC_None);
214
216
219
220 BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
221 HLSLParamModifierAttr::Spelling Modifier =
222 HLSLParamModifierAttr::Keyword_in);
223 QualType addTemplateTypeParam(StringRef Name);
225 template <typename... Ts>
226 BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
227 QualType ReturnType, Ts &&...ArgSpecs);
228 template <typename TLHS, typename TRHS>
229 BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
230 template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
231 template <typename V, typename S>
232 BuiltinTypeMethodBuilder &concat(V Vec, S Scalar, QualType ResultTy);
233
234 template <typename T>
236 template <typename T>
238 FieldDecl *Field);
239 template <typename ValueT>
240 BuiltinTypeMethodBuilder &setHandleFieldOnResource(LocalVar &ResourceRecord,
241 ValueT HandleValue);
242 template <typename ResourceT, typename ValueT>
243 BuiltinTypeMethodBuilder &setFieldOnResource(ResourceT ResourceRecord,
244 ValueT HandleValue,
245 FieldDecl *HandleField);
246 void setMipsHandleField(LocalVar &ResourceRecord);
247 template <typename T>
249 accessCounterHandleFieldOnResource(T ResourceRecord);
250 template <typename ResourceT, typename ValueT>
252 setCounterHandleFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue);
253 template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
259
260private:
261 void createDecl();
262
263 // Makes sure the declaration is created; should be called before any
264 // statement added to the body or when access to 'this' is needed.
265 void ensureCompleteDecl() {
266 if (!Method)
267 createDecl();
268 }
269};
270
274
277 QualType DefaultValue) {
278 assert(!Builder.Record->isCompleteDefinition() &&
279 "record is already complete");
280 ASTContext &AST = Builder.SemaRef.getASTContext();
281 unsigned Position = static_cast<unsigned>(Params.size());
283 AST, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(),
284 /* TemplateDepth */ 0, Position,
285 &AST.Idents.get(Name, tok::TokenKind::identifier),
286 /* Typename */ true,
287 /* ParameterPack */ false,
288 /* HasTypeConstraint*/ false);
289 if (!DefaultValue.isNull())
290 Decl->setDefaultArgument(AST,
291 Builder.SemaRef.getTrivialTemplateArgumentLoc(
292 DefaultValue, QualType(), SourceLocation()));
293
294 Params.emplace_back(Decl);
295 return *this;
296}
297
298// The concept specialization expression (CSE) constructed in
299// constructConceptSpecializationExpr is constructed so that it
300// matches the CSE that is constructed when parsing the below C++ code:
301//
302// template<typename T>
303// concept is_typed_resource_element_compatible =
304// __builtin_hlsl_typed_resource_element_compatible<T>
305//
306// template<typename element_type> requires
307// is_typed_resource_element_compatible<element_type>
308// struct RWBuffer {
309// element_type Val;
310// };
311//
312// int fn() {
313// RWBuffer<int> Buf;
314// }
315//
316// When dumping the AST and filtering for "RWBuffer", the resulting AST
317// structure is what we're trying to construct below, specifically the
318// CSE portion.
321 Sema &S, ConceptDecl *CD) {
322 ASTContext &Context = S.getASTContext();
323 SourceLocation Loc = Builder.Record->getBeginLoc();
324 DeclarationNameInfo DNI(CD->getDeclName(), Loc);
326 DeclContext *DC = Builder.Record->getDeclContext();
327 TemplateArgumentListInfo TALI(Loc, Loc);
328
329 // Assume that the concept decl has just one template parameter
330 // This parameter should have been added when CD was constructed
331 // in getTypedBufferConceptDecl
332 assert(CD->getTemplateParameters()->size() == 1 &&
333 "unexpected concept decl parameter count");
334 TemplateTypeParmDecl *ConceptTTPD =
335 dyn_cast<TemplateTypeParmDecl>(CD->getTemplateParameters()->getParam(0));
336
337 // this TemplateTypeParmDecl is the template for the resource, and is
338 // used to construct a template argumentthat will be used
339 // to construct the ImplicitConceptSpecializationDecl
341 Context, // AST context
342 Builder.Record->getDeclContext(), // DeclContext
344 /*D=*/0, // Depth in the template parameter list
345 /*P=*/0, // Position in the template parameter list
346 /*Id=*/nullptr, // Identifier for 'T'
347 /*Typename=*/true, // Indicates this is a 'typename' or 'class'
348 /*ParameterPack=*/false, // Not a parameter pack
349 /*HasTypeConstraint=*/false // Has no type constraint
350 );
351
352 T->setDeclContext(DC);
353
354 QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
355
356 // this is the 2nd template argument node, on which
357 // the concept constraint is actually being applied: 'element_type'
358 TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
359
360 QualType CSETType = Context.getTypeDeclType(T);
361
362 // this is the 1st template argument node, which represents
363 // the abstract type that a concept would refer to: 'T'
364 TemplateArgument CSETA = TemplateArgument(CSETType);
365
366 ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
368 Context, Builder.Record->getDeclContext(), Loc, {CSETA});
369
370 // Constraint satisfaction is used to construct the
371 // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
372 // located at the bottom of the sample AST above.
373 const ConstraintSatisfaction CS(CD, {ConceptTA});
376
377 TALI.addArgument(TAL);
378 const ASTTemplateArgumentListInfo *ATALI =
380
381 // In the concept reference, ATALI is what adds the extra
382 // TemplateArgument node underneath CSE
383 ConceptReference *CR =
384 ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
385
387 ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
388
389 return CSE;
390}
391
394 if (Params.empty())
395 return Builder;
396
397 ASTContext &AST = Builder.SemaRef.Context;
399 CD ? constructConceptSpecializationExpr(Builder.SemaRef, CD) : nullptr;
400 auto *ParamList = TemplateParameterList::Create(
403 AST, Builder.Record->getDeclContext(), SourceLocation(),
404 DeclarationName(Builder.Record->getIdentifier()), ParamList,
405 Builder.Record);
406
407 Builder.Record->setDescribedClassTemplate(Builder.Template);
408 Builder.Template->setImplicit(true);
409 Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
410
411 // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
412 // make visible.
413 Builder.Template->setPreviousDecl(Builder.PrevTemplate);
414 Builder.Record->getDeclContext()->addDecl(Builder.Template);
415 Params.clear();
416
417 return Builder;
418}
419
420Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
421 if (PH == PlaceHolder::Handle)
422 return getResourceHandleExpr();
423 if (PH == PlaceHolder::CounterHandle)
425 if (PH == PlaceHolder::This) {
426 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
428 Method->getFunctionObjectParameterType(),
429 /*IsImplicit=*/true);
430 }
431
432 if (PH == PlaceHolder::LastStmt) {
433 assert(!StmtsList.empty() && "no statements in the list");
434 Stmt *LastStmt = StmtsList.pop_back_val();
435 assert(isa<ValueStmt>(LastStmt) && "last statement does not have a value");
436 return cast<ValueStmt>(LastStmt)->getExprStmt();
437 }
438
439 // All other placeholders are parameters (_N), and can be loaded as an
440 // LValue. It needs to be an LValue if the result expression will be used as
441 // the actual parameter for an out parameter. The dimension builtins are an
442 // example where this happens.
443 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
444 ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
445 return DeclRefExpr::Create(
446 AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
447 DeclarationNameInfo(ParamDecl->getDeclName(), SourceLocation()),
448 ParamDecl->getType().getNonReferenceType(), VK_LValue);
449}
450
451Expr *BuiltinTypeMethodBuilder::convertPlaceholder(LocalVar &Var) {
452 VarDecl *VD = Var.Decl;
453 assert(VD && "local variable is not declared");
454 return DeclRefExpr::Create(
455 VD->getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
456 false, DeclarationNameInfo(VD->getDeclName(), SourceLocation()),
457 VD->getType(), VK_LValue);
458}
459
460Expr *BuiltinTypeMethodBuilder::convertPlaceholder(QualType Ty) {
461 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
462 QualType PtrTy = AST.getPointerType(Ty);
463 // Creates a value-initialized null pointer of type Ty*.
464 return new (AST) CXXScalarValueInitExpr(
465 PtrTy, AST.getTrivialTypeSourceInfo(PtrTy, SourceLocation()),
466 SourceLocation());
467}
468
470 StringRef NameStr,
471 QualType ReturnTy,
472 bool IsConst, bool IsCtor,
473 StorageClass SC)
474 : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
475 IsCtor(IsCtor), SC(SC) {
476
477 assert((!NameStr.empty() || IsCtor) && "method needs a name");
478 assert(((IsCtor && !IsConst) || !IsCtor) && "constructor cannot be const");
479
480 ASTContext &AST = DB.SemaRef.getASTContext();
481 if (IsCtor) {
483 AST.getCanonicalTagType(DB.Record));
484 } else {
485 const IdentifierInfo &II =
486 AST.Idents.get(NameStr, tok::TokenKind::identifier);
487 Name = DeclarationName(&II);
488 }
489}
490
493 HLSLParamModifierAttr::Spelling Modifier) {
494 assert(Method == nullptr && "Cannot add param, method already created");
495 const IdentifierInfo &II = DeclBuilder.SemaRef.getASTContext().Idents.get(
496 Name, tok::TokenKind::identifier);
497 Params.emplace_back(II, Ty, Modifier);
498 return *this;
499}
501 assert(Method == nullptr &&
502 "Cannot add template param, method already created");
503 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
504 unsigned Position = static_cast<unsigned>(TemplateParamDecls.size());
506 AST, DeclBuilder.Record, SourceLocation(), SourceLocation(),
507 /* TemplateDepth */ 0, Position,
508 &AST.Idents.get(Name, tok::TokenKind::identifier),
509 /* Typename */ true,
510 /* ParameterPack */ false,
511 /* HasTypeConstraint*/ false);
512 TemplateParamDecls.push_back(Decl);
513
514 return QualType(Decl->getTypeForDecl(), 0);
515}
516
517void BuiltinTypeMethodBuilder::createDecl() {
518 assert(Method == nullptr && "Method or constructor is already created");
519
520 // create function prototype
521 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
522 SmallVector<QualType> ParamTypes;
523 SmallVector<FunctionType::ExtParameterInfo> ParamExtInfos(Params.size());
524 uint32_t ArgIndex = 0;
525
526 // Create function prototype.
527 bool UseParamExtInfo = false;
528 for (Param &MP : Params) {
529 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
530 UseParamExtInfo = true;
531 FunctionType::ExtParameterInfo &PI = ParamExtInfos[ArgIndex];
532 ParamExtInfos[ArgIndex] =
533 PI.withABI(convertParamModifierToParamABI(MP.Modifier));
534 if (!MP.Ty->isDependentType())
535 MP.Ty = getInoutParameterType(AST, MP.Ty);
536 }
537 ParamTypes.emplace_back(MP.Ty);
538 ++ArgIndex;
539 }
540
541 FunctionProtoType::ExtProtoInfo ExtInfo;
542 if (UseParamExtInfo)
543 ExtInfo.ExtParameterInfos = ParamExtInfos.data();
544 if (IsConst)
545 ExtInfo.TypeQuals.addConst();
546
547 QualType FuncTy = AST.getFunctionType(ReturnTy, ParamTypes, ExtInfo);
548
549 // Create method or constructor declaration.
550 auto *TSInfo = AST.getTrivialTypeSourceInfo(FuncTy, SourceLocation());
551 DeclarationNameInfo NameInfo = DeclarationNameInfo(Name, SourceLocation());
552 if (IsCtor)
554 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo,
555 ExplicitSpecifier(), false, /*IsInline=*/true, false,
557 else
558 Method = CXXMethodDecl::Create(
559 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo, SC,
560 false, true, ConstexprSpecKind::Unspecified, SourceLocation());
561
562 // Create params & set them to the method/constructor and function prototype.
564 unsigned CurScopeDepth = DeclBuilder.SemaRef.getCurScope()->getDepth();
565 auto FnProtoLoc =
566 Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
567 for (int I = 0, E = Params.size(); I != E; I++) {
568 Param &MP = Params[I];
569 ParmVarDecl *Parm = ParmVarDecl::Create(
570 AST, Method, SourceLocation(), SourceLocation(), &MP.NameII, MP.Ty,
571 AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None,
572 nullptr);
573 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
574 auto *Mod =
575 HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
576 Parm->addAttr(Mod);
577 }
578 Parm->setScopeInfo(CurScopeDepth, I);
579 ParmDecls.push_back(Parm);
580 FnProtoLoc.setParam(I, Parm);
581 }
582 Method->setParams({ParmDecls});
583}
584
586 ensureCompleteDecl();
587
588 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
590 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
591 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
592 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
593 HandleField->getType(), VK_LValue,
595}
596
598 ensureCompleteDecl();
599
600 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
602 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
603 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
604 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
605 HandleField->getType(), VK_LValue,
607}
608
611 ensureCompleteDecl();
612
613 assert(Var.Decl == nullptr && "local variable is already declared");
614
615 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
616 Var.Decl = VarDecl::Create(
617 AST, Method, SourceLocation(), SourceLocation(),
618 &AST.Idents.get(Var.Name, tok::TokenKind::identifier), Var.Ty,
620 DeclStmt *DS = new (AST) clang::DeclStmt(DeclGroupRef(Var.Decl),
622 StmtsList.push_back(DS);
623 return *this;
624}
625
626template <typename V, typename S>
628 QualType ResultTy) {
629 assert(ResultTy->isVectorType() && "The result type must be a vector type.");
630 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
631 Expr *VecExpr = convertPlaceholder(Vec);
632 auto *VecTy = VecExpr->getType()->castAs<VectorType>();
633 Expr *ScalarExpr = convertPlaceholder(Scalar);
634
635 // Save the vector to a local variable to avoid evaluating the placeholder
636 // multiple times or sharing the AST node.
637 LocalVar VecVar("vec_tmp", VecTy->desugar());
638 declareLocalVar(VecVar);
639 assign(VecVar, VecExpr);
640
641 QualType EltTy = VecTy->getElementType();
642 unsigned NumElts = VecTy->getNumElements();
643
645 for (unsigned I = 0; I < NumElts; ++I) {
646 Elts.push_back(new (AST) ArraySubscriptExpr(
647 convertPlaceholder(VecVar), DeclBuilder.getConstantIntExpr(I), EltTy,
649 }
650 Elts.push_back(ScalarExpr);
651
652 auto *InitList =
653 new (AST) InitListExpr(AST, SourceLocation(), Elts, SourceLocation());
654 InitList->setType(ResultTy);
655
656 ExprResult Cast = DeclBuilder.SemaRef.BuildCStyleCastExpr(
658 SourceLocation(), InitList);
659 assert(!Cast.isInvalid() && "Cast cannot fail!");
660 StmtsList.push_back(Cast.get());
661
662 return *this;
663}
664
666 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
668 AST, SourceLocation(), Method->getFunctionObjectParameterType(),
669 /*IsImplicit=*/true);
670 StmtsList.push_back(ThisExpr);
671 return *this;
672}
673
674template <typename... Ts>
677 QualType ReturnType, Ts &&...ArgSpecs) {
678 ensureCompleteDecl();
679
680 std::array<Expr *, sizeof...(ArgSpecs)> Args{
681 convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
682
683 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
684 FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
686 AST, NestedNameSpecifierLoc(), SourceLocation(), FD, false,
688
689 ExprResult Call = DeclBuilder.SemaRef.BuildCallExpr(
690 /*Scope=*/nullptr, DRE, SourceLocation(),
691 MultiExprArg(Args.data(), Args.size()), SourceLocation());
692 assert(!Call.isInvalid() && "Call to builtin cannot fail!");
693 Expr *E = Call.get();
694
695 if (!ReturnType.isNull() &&
696 !AST.hasSameUnqualifiedType(ReturnType, E->getType())) {
697 ExprResult CastResult = DeclBuilder.SemaRef.BuildCStyleCastExpr(
698 SourceLocation(), AST.getTrivialTypeSourceInfo(ReturnType),
699 SourceLocation(), E);
700 assert(!CastResult.isInvalid() && "Cast cannot fail!");
701 E = CastResult.get();
702 }
703
704 StmtsList.push_back(E);
705 return *this;
706}
707
708template <typename TLHS, typename TRHS>
710 Expr *LHSExpr = convertPlaceholder(LHS);
711 Expr *RHSExpr = convertPlaceholder(RHS);
712 Stmt *AssignStmt = BinaryOperator::Create(
713 DeclBuilder.SemaRef.getASTContext(), LHSExpr, RHSExpr, BO_Assign,
716 StmtsList.push_back(AssignStmt);
717 return *this;
718}
719
720template <typename T>
722 Expr *PtrExpr = convertPlaceholder(Ptr);
723 Expr *Deref =
724 UnaryOperator::Create(DeclBuilder.SemaRef.getASTContext(), PtrExpr,
725 UO_Deref, PtrExpr->getType()->getPointeeType(),
727 /*CanOverflow=*/false, FPOptionsOverride());
728 StmtsList.push_back(Deref);
729 return *this;
730}
731
732template <typename T>
735 ensureCompleteDecl();
736
737 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
738 auto *ResourceTypeDecl = ResourceExpr->getType()->getAsCXXRecordDecl();
739
740 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
741 FieldDecl *HandleField = nullptr;
742
743 if (ResourceTypeDecl == DeclBuilder.Record)
744 HandleField = DeclBuilder.getResourceHandleField();
745 else {
746 IdentifierInfo &II = AST.Idents.get("__handle");
747 for (auto *Decl : ResourceTypeDecl->lookup(&II)) {
748 if ((HandleField = dyn_cast<FieldDecl>(Decl)))
749 break;
750 }
751 assert(HandleField && "Resource handle field not found");
752 }
753
755 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
757 StmtsList.push_back(HandleExpr);
758 return *this;
759}
760
761template <typename T>
764 FieldDecl *Field) {
765 ensureCompleteDecl();
766 Expr *Base = convertPlaceholder(ResourceRecord);
767
768 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
769 auto *Member =
770 MemberExpr::CreateImplicit(AST, Base, /*IsArrow=*/false, Field,
771 Field->getType(), VK_LValue, OK_Ordinary);
772 StmtsList.push_back(Member);
773 return *this;
774}
775
776void BuiltinTypeMethodBuilder::setMipsHandleField(LocalVar &ResourceRecord) {
777 FieldDecl *MipsField = DeclBuilder.Fields.lookup("mips");
778 if (!MipsField)
779 return;
780
781 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
782 QualType MipsTy = MipsField->getType();
783 const auto *RT = MipsTy->castAs<RecordType>();
784 CXXRecordDecl *MipsRecord = cast<CXXRecordDecl>(RT->getDecl());
785
786 // The mips record should have a single field that is the handle.
787 assert(MipsRecord->field_begin() != MipsRecord->field_end() &&
788 "mips_type must have at least one field");
789 assert(std::next(MipsRecord->field_begin()) == MipsRecord->field_end() &&
790 "mips_type must have exactly one field");
791 FieldDecl *MipsHandleField = *MipsRecord->field_begin();
792
793 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
794 Expr *ResExpr = convertPlaceholder(ResourceRecord);
795 MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
796 AST, ResExpr, false, HandleField, HandleField->getType(), VK_LValue,
798
799 MemberExpr *MipsMemberExpr =
800 MemberExpr::CreateImplicit(AST, ResExpr, false, MipsField,
801 MipsField->getType(), VK_LValue, OK_Ordinary);
802 MemberExpr *MipsHandleMemberExpr = MemberExpr::CreateImplicit(
803 AST, MipsMemberExpr, false, MipsHandleField, MipsHandleField->getType(),
805
806 Stmt *AssignStmt = BinaryOperator::Create(
807 AST, MipsHandleMemberExpr, HandleMemberExpr, BO_Assign,
808 MipsHandleMemberExpr->getType(), ExprValueKind::VK_LValue,
810
811 StmtsList.push_back(AssignStmt);
812}
813
814template <typename ValueT>
817 ValueT HandleValue) {
818 setFieldOnResource(ResourceRecord, HandleValue,
819 DeclBuilder.getResourceHandleField());
820 setMipsHandleField(ResourceRecord);
821 return *this;
822}
823
824template <typename ResourceT, typename ValueT>
827 ResourceT ResourceRecord, ValueT HandleValue) {
828 return setFieldOnResource(ResourceRecord, HandleValue,
829 DeclBuilder.getResourceCounterHandleField());
830}
831
832template <typename ResourceT, typename ValueT>
834 ResourceT ResourceRecord, ValueT HandleValue, FieldDecl *HandleField) {
835 ensureCompleteDecl();
836
837 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
838 assert(ResourceExpr->getType()->getAsCXXRecordDecl() ==
839 HandleField->getParent() &&
840 "Getting the field from the wrong resource type.");
841
842 Expr *HandleValueExpr = convertPlaceholder(HandleValue);
843
844 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
845 MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
846 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
848 Stmt *AssignStmt = BinaryOperator::Create(
849 DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr,
850 BO_Assign, HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
852 StmtsList.push_back(AssignStmt);
853 return *this;
854}
855
856template <typename T>
859 ensureCompleteDecl();
860
861 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
862 assert(ResourceExpr->getType()->getAsCXXRecordDecl() == DeclBuilder.Record &&
863 "Getting the field from the wrong resource type.");
864
865 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
866 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
868 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
870 StmtsList.push_back(HandleExpr);
871 return *this;
872}
873
874template <typename T>
876 ensureCompleteDecl();
877
878 Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
879 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
880
881 QualType Ty = ReturnValueExpr->getType();
882 if (Ty->isRecordType()) {
883 // For record types, create a call to copy constructor to ensure proper copy
884 // semantics.
885 auto *ICE =
886 ImplicitCastExpr::Create(AST, Ty.withConst(), CK_NoOp, ReturnValueExpr,
887 nullptr, VK_XValue, FPOptionsOverride());
888 CXXConstructorDecl *CD = lookupCopyConstructor(Ty);
889 assert(CD && "no copy constructor found");
890 ReturnValueExpr = CXXConstructExpr::Create(
891 AST, Ty, SourceLocation(), CD, /*Elidable=*/false, {ICE},
892 /*HadMultipleCandidates=*/false, /*ListInitialization=*/false,
893 /*StdInitListInitialization=*/false,
894 /*ZeroInitListInitialization=*/false, CXXConstructionKind::Complete,
895 SourceRange());
896 }
897 StmtsList.push_back(
898 ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
899 return *this;
900}
901
904 assert(!DeclBuilder.Record->isCompleteDefinition() &&
905 "record is already complete");
906
907 ensureCompleteDecl();
908
909 if (!Method->hasBody()) {
910 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
911 assert((ReturnTy == AST.VoidTy || !StmtsList.empty()) &&
912 "nothing to return from non-void method");
913 if (ReturnTy != AST.VoidTy) {
914 if (Expr *LastExpr = dyn_cast<Expr>(StmtsList.back())) {
915 assert(AST.hasSameUnqualifiedType(LastExpr->getType(),
916 ReturnTy.getNonReferenceType()) &&
917 "Return type of the last statement must match the return type "
918 "of the method");
919 if (!isa<ReturnStmt>(LastExpr)) {
920 StmtsList.pop_back();
921 StmtsList.push_back(
922 ReturnStmt::Create(AST, SourceLocation(), LastExpr, nullptr));
923 }
924 }
925 }
926
927 Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
929 Method->setLexicalDeclContext(DeclBuilder.Record);
930 Method->setAccess(Access);
931 Method->setImplicitlyInline();
932 Method->addAttr(AlwaysInlineAttr::CreateImplicit(
933 AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
934 Method->addAttr(ConvergentAttr::CreateImplicit(AST));
935 if (!TemplateParamDecls.empty()) {
936 TemplateParams = TemplateParameterList::Create(
937 AST, SourceLocation(), SourceLocation(), TemplateParamDecls,
938 SourceLocation(), nullptr);
939
940 auto *FuncTemplate = FunctionTemplateDecl::Create(AST, DeclBuilder.Record,
941 SourceLocation(), Name,
942 TemplateParams, Method);
943 FuncTemplate->setAccess(AS_public);
944 FuncTemplate->setLexicalDeclContext(DeclBuilder.Record);
945 FuncTemplate->setImplicit(true);
946 Method->setDescribedFunctionTemplate(FuncTemplate);
947 DeclBuilder.Record->addDecl(FuncTemplate);
948 } else {
949 DeclBuilder.Record->addDecl(Method);
950 }
951 }
952 return DeclBuilder;
953}
954
956 : SemaRef(SemaRef), Record(R) {
957 Record->startDefinition();
958 Template = Record->getDescribedClassTemplate();
959}
960
962 NamespaceDecl *Namespace,
963 StringRef Name)
964 : SemaRef(SemaRef), HLSLNamespace(Namespace) {
965 ASTContext &AST = SemaRef.getASTContext();
966 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
967
969 CXXRecordDecl *PrevDecl = nullptr;
970 if (SemaRef.LookupQualifiedName(Result, HLSLNamespace)) {
971 // Declaration already exists (from precompiled headers)
972 NamedDecl *Found = Result.getFoundDecl();
973 if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
974 PrevDecl = TD->getTemplatedDecl();
975 PrevTemplate = TD;
976 } else
977 PrevDecl = dyn_cast<CXXRecordDecl>(Found);
978 assert(PrevDecl && "Unexpected lookup result type.");
979 }
980
981 if (PrevDecl && PrevDecl->isCompleteDefinition()) {
982 Record = PrevDecl;
983 Template = PrevTemplate;
984 return;
985 }
986
987 Record =
988 CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
989 SourceLocation(), SourceLocation(), &II, PrevDecl);
990 Record->setImplicit(true);
991 Record->setLexicalDeclContext(HLSLNamespace);
992 Record->setHasExternalLexicalStorage();
993
994 // Don't let anyone derive from built-in types.
995 Record->addAttr(
996 FinalAttr::CreateImplicit(AST, SourceRange(), FinalAttr::Keyword_final));
997}
998
1000 if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
1001 HLSLNamespace->addDecl(Record);
1002}
1003
1007 AccessSpecifier Access) {
1008 assert(!Record->isCompleteDefinition() && "record is already complete");
1009 assert(Record->isBeingDefined() &&
1010 "Definition must be started before adding members!");
1011 ASTContext &AST = Record->getASTContext();
1012
1013 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
1014 TypeSourceInfo *MemTySource =
1016 auto *Field = FieldDecl::Create(
1017 AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
1018 nullptr, false, InClassInitStyle::ICIS_NoInit);
1019 Field->setAccess(Access);
1020 Field->setImplicit(true);
1021 for (Attr *A : Attrs) {
1022 if (A)
1023 Field->addAttr(A);
1024 }
1025
1026 Record->addDecl(Field);
1027 Fields[Name] = Field;
1028 return *this;
1029}
1030
1032BuiltinTypeDeclBuilder::addBufferHandles(ResourceClass RC, bool IsROV,
1033 bool RawBuffer, bool HasCounter,
1034 AccessSpecifier Access) {
1035 QualType ElementTy = getHandleElementType();
1036 addHandleMember(RC, ResourceDimension::Unknown, IsROV, RawBuffer, ElementTy,
1037 Access);
1038 if (HasCounter)
1039 addCounterHandleMember(RC, IsROV, RawBuffer, ElementTy, Access);
1040 return *this;
1041}
1042
1044BuiltinTypeDeclBuilder::addTextureHandle(ResourceClass RC, bool IsROV,
1045 ResourceDimension RD,
1046 AccessSpecifier Access) {
1047 addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, getHandleElementType(),
1048 Access);
1049 return *this;
1050}
1051
1053 addHandleMember(ResourceClass::Sampler, ResourceDimension::Unknown,
1054 /*IsROV=*/false, /*RawBuffer=*/false, getHandleElementType());
1055 return *this;
1056}
1057
1059BuiltinTypeDeclBuilder::addFriend(CXXRecordDecl *Friend) {
1060 assert(!Record->isCompleteDefinition() && "record is already complete");
1061 ASTContext &AST = SemaRef.getASTContext();
1062 QualType FriendTy = AST.getCanonicalTagType(Friend);
1063 TypeSourceInfo *TSI = AST.getTrivialTypeSourceInfo(FriendTy);
1064 FriendDecl *FD =
1066 FD->setAccess(AS_public);
1067 Record->addDecl(FD);
1068 return *this;
1069}
1070
1071CXXRecordDecl *BuiltinTypeDeclBuilder::addPrivateNestedRecord(StringRef Name) {
1072 assert(!Record->isCompleteDefinition() && "record is already complete");
1073 ASTContext &AST = SemaRef.getASTContext();
1074 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
1075 CXXRecordDecl *NestedRecord =
1076 CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, Record,
1077 SourceLocation(), SourceLocation(), &II);
1078 NestedRecord->setImplicit(true);
1080 NestedRecord->setLexicalDeclContext(Record);
1081 Record->addDecl(NestedRecord);
1082 return NestedRecord;
1083}
1084
1085BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
1086 ResourceClass RC, ResourceDimension RD, bool IsROV, bool RawBuffer,
1087 QualType ElementTy, AccessSpecifier Access) {
1088 return addResourceMember("__handle", RC, RD, IsROV, RawBuffer,
1089 /*IsCounter=*/false, ElementTy, Access);
1090}
1091
1092BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
1093 ResourceClass RC, bool IsROV, bool RawBuffer, QualType ElementTy,
1094 AccessSpecifier Access) {
1095 return addResourceMember("__counter_handle", RC, ResourceDimension::Unknown,
1096 IsROV, RawBuffer,
1097 /*IsCounter=*/true, ElementTy, Access);
1098}
1099
1100BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember(
1101 StringRef MemberName, ResourceClass RC, ResourceDimension RD, bool IsROV,
1102 bool RawBuffer, bool IsCounter, QualType ElementTy,
1103 AccessSpecifier Access) {
1104 assert(!Record->isCompleteDefinition() && "record is already complete");
1105
1106 ASTContext &Ctx = SemaRef.getASTContext();
1107
1108 assert(!ElementTy.isNull() &&
1109 "The caller should always pass in the type for the handle.");
1110 TypeSourceInfo *ElementTypeInfo =
1111 Ctx.getTrivialTypeSourceInfo(ElementTy, SourceLocation());
1112
1113 // add handle member with resource type attributes
1114 QualType AttributedResTy = QualType();
1115 SmallVector<const Attr *> Attrs = {
1116 HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
1117 IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
1118 RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
1119 RD != ResourceDimension::Unknown
1120 ? HLSLResourceDimensionAttr::CreateImplicit(Ctx, RD)
1121 : nullptr,
1122 ElementTypeInfo && RC != ResourceClass::Sampler
1123 ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
1124 : nullptr};
1125 if (IsCounter)
1126 Attrs.push_back(HLSLIsCounterAttr::CreateImplicit(Ctx));
1127
1128 if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
1129 AttributedResTy))
1130 addMemberVariable(MemberName, AttributedResTy, {}, Access);
1131 return *this;
1132}
1133
1134// Adds default constructor to the resource class:
1135// Resource::Resource()
1138 assert(!Record->isCompleteDefinition() && "record is already complete");
1139
1140 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1141 QualType HandleType = getResourceHandleField()->getType();
1142 return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
1143 false, true)
1144 .callBuiltin("__builtin_hlsl_resource_uninitializedhandle", HandleType,
1145 PH::Handle)
1146 .assign(PH::Handle, PH::LastStmt)
1147 .finalize(Access);
1148}
1149
1152 if (HasCounter) {
1153 addCreateFromBindingWithImplicitCounter();
1154 addCreateFromImplicitBindingWithImplicitCounter();
1155 } else {
1156 addCreateFromBinding();
1157 addCreateFromImplicitBinding();
1158 }
1159 return *this;
1160}
1161
1162// Adds static method that initializes resource from binding:
1163//
1164// static Resource<T> __createFromBinding(unsigned registerNo,
1165// unsigned spaceNo, int range,
1166// unsigned index, const char *name) {
1167// Resource<T> tmp;
1168// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1169// tmp.__handle, registerNo, spaceNo,
1170// range, index, name);
1171// return tmp;
1172// }
1173BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
1174 assert(!Record->isCompleteDefinition() && "record is already complete");
1175
1176 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1177 ASTContext &AST = SemaRef.getASTContext();
1178 QualType HandleType = getResourceHandleField()->getType();
1179 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1180 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1181
1182 return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
1183 false, false, SC_Static)
1184 .addParam("registerNo", AST.UnsignedIntTy)
1185 .addParam("spaceNo", AST.UnsignedIntTy)
1186 .addParam("range", AST.IntTy)
1187 .addParam("index", AST.UnsignedIntTy)
1188 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1189 .declareLocalVar(TmpVar)
1190 .accessHandleFieldOnResource(TmpVar)
1191 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1192 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1193 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1194 .returnValue(TmpVar)
1195 .finalize();
1196}
1197
1198// Adds static method that initializes resource from binding:
1199//
1200// static Resource<T> __createFromImplicitBinding(unsigned orderId,
1201// unsigned spaceNo, int range,
1202// unsigned index,
1203// const char *name) {
1204// Resource<T> tmp;
1205// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1206// tmp.__handle, spaceNo,
1207// range, index, orderId, name);
1208// return tmp;
1209// }
1210BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
1211 assert(!Record->isCompleteDefinition() && "record is already complete");
1212
1213 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1214 ASTContext &AST = SemaRef.getASTContext();
1215 QualType HandleType = getResourceHandleField()->getType();
1216 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1217 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1218
1219 return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
1220 RecordType, false, false, SC_Static)
1221 .addParam("orderId", AST.UnsignedIntTy)
1222 .addParam("spaceNo", AST.UnsignedIntTy)
1223 .addParam("range", AST.IntTy)
1224 .addParam("index", AST.UnsignedIntTy)
1225 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1226 .declareLocalVar(TmpVar)
1227 .accessHandleFieldOnResource(TmpVar)
1228 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1229 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1230 PH::_4)
1231 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1232 .returnValue(TmpVar)
1233 .finalize();
1234}
1235
1236// Adds static method that initializes resource from binding:
1237//
1238// static Resource<T>
1239// __createFromBindingWithImplicitCounter(unsigned registerNo,
1240// unsigned spaceNo, int range,
1241// unsigned index, const char *name,
1242// unsigned counterOrderId) {
1243// Resource<T> tmp;
1244// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1245// tmp.__handle, registerNo, spaceNo, range, index, name);
1246// tmp.__counter_handle =
1247// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1248// tmp.__handle, counterOrderId, spaceNo);
1249// return tmp;
1250// }
1252BuiltinTypeDeclBuilder::addCreateFromBindingWithImplicitCounter() {
1253 assert(!Record->isCompleteDefinition() && "record is already complete");
1254
1255 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1256 ASTContext &AST = SemaRef.getASTContext();
1257 QualType HandleType = getResourceHandleField()->getType();
1258 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1259 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1260 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1261
1262 return BuiltinTypeMethodBuilder(*this,
1263 "__createFromBindingWithImplicitCounter",
1264 RecordType, false, false, SC_Static)
1265 .addParam("registerNo", AST.UnsignedIntTy)
1266 .addParam("spaceNo", AST.UnsignedIntTy)
1267 .addParam("range", AST.IntTy)
1268 .addParam("index", AST.UnsignedIntTy)
1269 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1270 .addParam("counterOrderId", AST.UnsignedIntTy)
1271 .declareLocalVar(TmpVar)
1272 .accessHandleFieldOnResource(TmpVar)
1273 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1274 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1275 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1276 .accessHandleFieldOnResource(TmpVar)
1277 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1278 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1279 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1280 .returnValue(TmpVar)
1281 .finalize();
1282}
1283
1284// Adds static method that initializes resource from binding:
1285//
1286// static Resource<T>
1287// __createFromImplicitBindingWithImplicitCounter(unsigned orderId,
1288// unsigned spaceNo, int range,
1289// unsigned index,
1290// const char *name,
1291// unsigned counterOrderId) {
1292// Resource<T> tmp;
1293// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1294// tmp.__handle, orderId, spaceNo, range, index, name);
1295// tmp.__counter_handle =
1296// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1297// tmp.__handle, counterOrderId, spaceNo);
1298// return tmp;
1299// }
1301BuiltinTypeDeclBuilder::addCreateFromImplicitBindingWithImplicitCounter() {
1302 assert(!Record->isCompleteDefinition() && "record is already complete");
1303
1304 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1305 ASTContext &AST = SemaRef.getASTContext();
1306 QualType HandleType = getResourceHandleField()->getType();
1307 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1308 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1309 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1310
1312 *this, "__createFromImplicitBindingWithImplicitCounter",
1313 RecordType, false, false, SC_Static)
1314 .addParam("orderId", AST.UnsignedIntTy)
1315 .addParam("spaceNo", AST.UnsignedIntTy)
1316 .addParam("range", AST.IntTy)
1317 .addParam("index", AST.UnsignedIntTy)
1318 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1319 .addParam("counterOrderId", AST.UnsignedIntTy)
1320 .declareLocalVar(TmpVar)
1321 .accessHandleFieldOnResource(TmpVar)
1322 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1323 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1324 PH::_4)
1325 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1326 .accessHandleFieldOnResource(TmpVar)
1327 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1328 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1329 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1330 .returnValue(TmpVar)
1331 .finalize();
1332}
1333
1336 assert(!Record->isCompleteDefinition() && "record is already complete");
1337
1338 ASTContext &AST = SemaRef.getASTContext();
1339 QualType RecordType = AST.getCanonicalTagType(Record);
1340 QualType ConstRecordType = RecordType.withConst();
1341 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1342
1343 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1344
1345 BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy,
1346 /*IsConst=*/false, /*IsCtor=*/true);
1347 MMB.addParam("other", ConstRecordRefType);
1348
1349 for (auto *Field : Record->fields()) {
1350 MMB.accessFieldOnResource(PH::_0, Field)
1351 .setFieldOnResource(PH::This, PH::LastStmt, Field);
1352 }
1353
1354 return MMB.finalize(Access);
1355}
1356
1359 assert(!Record->isCompleteDefinition() && "record is already complete");
1360
1361 ASTContext &AST = SemaRef.getASTContext();
1362 QualType RecordType = AST.getCanonicalTagType(Record);
1363 QualType ConstRecordType = RecordType.withConst();
1364 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1365 QualType RecordRefType = AST.getLValueReferenceType(RecordType);
1366
1367 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1369 BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType);
1370 MMB.addParam("other", ConstRecordRefType);
1371
1372 for (auto *Field : Record->fields()) {
1373 MMB.accessFieldOnResource(PH::_0, Field)
1374 .setFieldOnResource(PH::This, PH::LastStmt, Field);
1375 }
1376
1377 return MMB.returnThis().finalize(Access);
1378}
1379
1382 assert(!Record->isCompleteDefinition() && "record is already complete");
1383 ASTContext &AST = Record->getASTContext();
1384
1385 uint32_t VecSize = 1;
1386 if (Dim != ResourceDimension::Unknown)
1387 VecSize = getResourceDimensions(Dim);
1388
1389 QualType IndexTy = VecSize > 1
1390 ? AST.getExtVectorType(AST.UnsignedIntTy, VecSize)
1391 : AST.UnsignedIntTy;
1392
1393 DeclarationName Subscript =
1394 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1395
1396 addHandleAccessFunction(Subscript, /*IsConst=*/true, /*IsRef=*/true, IndexTy);
1397 if (getResourceAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV)
1398 addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true,
1399 IndexTy);
1400
1401 return *this;
1402}
1403
1405 assert(!Record->isCompleteDefinition() && "record is already complete");
1406
1407 ASTContext &AST = Record->getASTContext();
1408 IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
1409 DeclarationName Load(&II);
1410 // TODO: We also need versions with status for CheckAccessFullyMapped.
1411 addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false,
1412 AST.UnsignedIntTy);
1413 addLoadWithStatusFunction(Load, /*IsConst=*/false);
1414
1415 return *this;
1416}
1417
1418CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsSliceType(ResourceDimension Dim,
1419 QualType ReturnType) {
1420 ASTContext &AST = Record->getASTContext();
1421 uint32_t VecSize = getResourceDimensions(Dim);
1422 QualType IntTy = AST.IntTy;
1423 QualType IndexTy = VecSize > 1 ? AST.getExtVectorType(IntTy, VecSize) : IntTy;
1424 QualType CoordLevelTy = AST.getExtVectorType(IntTy, VecSize + 1);
1425 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1426
1427 // Define the mips_slice_type which is returned by mips_type::operator[].
1428 // It holds the resource handle and the mip level. It has an operator[]
1429 // that takes the coordinate and performs the actual resource load.
1430 CXXRecordDecl *MipsSliceRecord = addPrivateNestedRecord("mips_slice_type");
1431 BuiltinTypeDeclBuilder MipsSliceBuilder(SemaRef, MipsSliceRecord);
1432 MipsSliceBuilder.addFriend(Record)
1433 .addHandleMember(getResourceAttrs().ResourceClass, Dim,
1434 getResourceAttrs().IsROV, false, ReturnType,
1436 .addMemberVariable("__level", IntTy, {}, AccessSpecifier::AS_public)
1440
1441 FieldDecl *LevelField = MipsSliceBuilder.Fields["__level"];
1442 assert(LevelField && "Could not find the level field.");
1443
1444 DeclarationName SubscriptName =
1445 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1446
1447 // operator[](intN coord) on mips_slice_type
1448 BuiltinTypeMethodBuilder(MipsSliceBuilder, SubscriptName, ReturnType,
1449 /*IsConst=*/true)
1450 .addParam("Coord", IndexTy)
1451 .accessFieldOnResource(PH::This, LevelField)
1452 .concat(PH::_0, PH::LastStmt, CoordLevelTy)
1453 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1454 PH::LastStmt)
1455 .finalize();
1456
1457 MipsSliceBuilder.completeDefinition();
1458 return MipsSliceRecord;
1459}
1460
1461CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsType(ResourceDimension Dim,
1462 QualType ReturnType) {
1463 ASTContext &AST = Record->getASTContext();
1464 QualType IntTy = AST.IntTy;
1465 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1466
1467 // First, define the mips_slice_type that will be returned by our operator[].
1468 CXXRecordDecl *MipsSliceRecord = addMipsSliceType(Dim, ReturnType);
1469
1470 // Define the mips_type, which provides the syntax `Resource.mips[level]`.
1471 // It only holds the handle, and its operator[] returns a mips_slice_type
1472 // initialized with the handle and the requested mip level.
1473 CXXRecordDecl *MipsRecord = addPrivateNestedRecord("mips_type");
1474 BuiltinTypeDeclBuilder MipsBuilder(SemaRef, MipsRecord);
1475 MipsBuilder.addFriend(Record)
1476 .addHandleMember(getResourceAttrs().ResourceClass, Dim,
1477 getResourceAttrs().IsROV, false, ReturnType,
1479 .addDefaultHandleConstructor(AccessSpecifier::AS_protected)
1480 .addCopyConstructor(AccessSpecifier::AS_protected)
1481 .addCopyAssignmentOperator(AccessSpecifier::AS_protected);
1482
1483 QualType MipsSliceTy = AST.getCanonicalTagType(MipsSliceRecord);
1484
1485 DeclarationName SubscriptName =
1486 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1487
1488 // Locate the fields in the slice type so we can initialize them.
1489 auto FieldIt = MipsSliceRecord->field_begin();
1490 FieldDecl *MipsSliceHandleField = *FieldIt;
1491 FieldDecl *LevelField = *++FieldIt;
1492 assert(MipsSliceHandleField->getName() == "__handle" &&
1493 LevelField->getName() == "__level" &&
1494 "Could not find fields on mips_slice_type");
1495
1496 // operator[](int level) on mips_type
1497 BuiltinTypeMethodBuilder::LocalVar MipsSliceVar("slice", MipsSliceTy);
1498 BuiltinTypeMethodBuilder(MipsBuilder, SubscriptName, MipsSliceTy,
1499 /*IsConst=*/true)
1500 .addParam("Level", IntTy)
1501 .declareLocalVar(MipsSliceVar)
1502 .accessHandleFieldOnResource(PH::This)
1503 .setFieldOnResource(MipsSliceVar, PH::LastStmt, MipsSliceHandleField)
1504 .setFieldOnResource(MipsSliceVar, PH::_0, LevelField)
1505 .returnValue(MipsSliceVar)
1506 .finalize();
1507
1508 MipsBuilder.completeDefinition();
1509 return MipsRecord;
1510}
1511
1514 assert(!Record->isCompleteDefinition() && "record is already complete");
1515 ASTContext &AST = Record->getASTContext();
1516 QualType ReturnType = getHandleElementType();
1517
1518 CXXRecordDecl *MipsRecord = addMipsType(Dim, ReturnType);
1519
1520 // Add the mips field to the texture
1521 QualType MipsTy = AST.getCanonicalTagType(MipsRecord);
1522 addMemberVariable("mips", MipsTy, {}, AccessSpecifier::AS_public);
1523
1524 return *this;
1525}
1526
1529 assert(!Record->isCompleteDefinition() && "record is already complete");
1530 ASTContext &AST = Record->getASTContext();
1531 uint32_t VecSize = getResourceDimensions(Dim);
1532 QualType IntTy = AST.IntTy;
1533 QualType OffsetTy = AST.getExtVectorType(IntTy, VecSize);
1534 QualType LocationTy = AST.getExtVectorType(IntTy, VecSize + 1);
1535 QualType ReturnType = getHandleElementType();
1536
1537 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1538
1539 // T Load(int3 location)
1540 BuiltinTypeMethodBuilder(*this, "Load", ReturnType)
1541 .addParam("Location", LocationTy)
1542 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1543 PH::_0)
1544 .finalize();
1545
1546 // T Load(int3 location, int2 offset)
1547 return BuiltinTypeMethodBuilder(*this, "Load", ReturnType)
1548 .addParam("Location", LocationTy)
1549 .addParam("Offset", OffsetTy)
1550 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1551 PH::_0, PH::_1)
1552 .finalize();
1553}
1554
1557 assert(!Record->isCompleteDefinition() && "record is already complete");
1558
1559 ASTContext &AST = SemaRef.getASTContext();
1560
1561 auto AddLoads = [&](StringRef MethodName, QualType ReturnType) {
1562 IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
1563 DeclarationName Load(&II);
1564
1565 addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false,
1566 AST.UnsignedIntTy, ReturnType);
1567 addLoadWithStatusFunction(Load, /*IsConst=*/false, ReturnType);
1568 };
1569
1570 AddLoads("Load", AST.UnsignedIntTy);
1571 AddLoads("Load2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
1572 AddLoads("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
1573 AddLoads("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
1574 AddLoads("Load", AST.DependentTy); // Templated version
1575 return *this;
1576}
1577
1580 assert(!Record->isCompleteDefinition() && "record is already complete");
1581
1582 ASTContext &AST = SemaRef.getASTContext();
1583
1584 auto AddStore = [&](StringRef MethodName, QualType ValueType) {
1585 IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
1586 DeclarationName Store(&II);
1587
1588 addStoreFunction(Store, /*IsConst=*/false, ValueType);
1589 };
1590
1591 AddStore("Store", AST.UnsignedIntTy);
1592 AddStore("Store2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
1593 AddStore("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
1594 AddStore("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
1595 AddStore("Store", AST.DependentTy); // Templated version
1596
1597 return *this;
1598}
1599
1602 assert(!Record->isCompleteDefinition() && "record is already complete");
1603 ASTContext &AST = Record->getASTContext();
1604 QualType ReturnType = getHandleElementType();
1605 QualType SamplerStateType =
1606 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1607 uint32_t VecSize = getResourceDimensions(Dim);
1608 QualType FloatTy = AST.FloatTy;
1609 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1610 QualType IntTy = AST.IntTy;
1611 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1612 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1613
1614 // T Sample(SamplerState s, float2 location)
1615 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1616 .addParam("Sampler", SamplerStateType)
1617 .addParam("Location", Float2Ty)
1618 .accessHandleFieldOnResource(PH::_0)
1619 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1620 PH::LastStmt, PH::_1)
1621 .returnValue(PH::LastStmt)
1622 .finalize();
1623
1624 // T Sample(SamplerState s, float2 location, int2 offset)
1625 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1626 .addParam("Sampler", SamplerStateType)
1627 .addParam("Location", Float2Ty)
1628 .addParam("Offset", Int2Ty)
1629 .accessHandleFieldOnResource(PH::_0)
1630 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1631 PH::LastStmt, PH::_1, PH::_2)
1632 .returnValue(PH::LastStmt)
1633 .finalize();
1634
1635 // T Sample(SamplerState s, float2 location, int2 offset, float clamp)
1636 return BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1637 .addParam("Sampler", SamplerStateType)
1638 .addParam("Location", Float2Ty)
1639 .addParam("Offset", Int2Ty)
1640 .addParam("Clamp", FloatTy)
1641 .accessHandleFieldOnResource(PH::_0)
1642 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1643 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1644 .returnValue(PH::LastStmt)
1645 .finalize();
1646}
1647
1650 assert(!Record->isCompleteDefinition() && "record is already complete");
1651 ASTContext &AST = Record->getASTContext();
1652 QualType ReturnType = getHandleElementType();
1653 QualType SamplerStateType =
1654 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1655 uint32_t VecSize = getResourceDimensions(Dim);
1656 QualType FloatTy = AST.FloatTy;
1657 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1658 QualType IntTy = AST.IntTy;
1659 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1660 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1661
1662 // T SampleBias(SamplerState s, float2 location, float bias)
1663 BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1664 .addParam("Sampler", SamplerStateType)
1665 .addParam("Location", Float2Ty)
1666 .addParam("Bias", FloatTy)
1667 .accessHandleFieldOnResource(PH::_0)
1668 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1669 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1670 .returnValue(PH::LastStmt)
1671 .finalize();
1672
1673 // T SampleBias(SamplerState s, float2 location, float bias, int2 offset)
1674 BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1675 .addParam("Sampler", SamplerStateType)
1676 .addParam("Location", Float2Ty)
1677 .addParam("Bias", FloatTy)
1678 .addParam("Offset", Int2Ty)
1679 .accessHandleFieldOnResource(PH::_0)
1680 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1681 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1682 .returnValue(PH::LastStmt)
1683 .finalize();
1684
1685 // T SampleBias(SamplerState s, float2 location, float bias, int2 offset,
1686 // float clamp)
1687 return BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1688 .addParam("Sampler", SamplerStateType)
1689 .addParam("Location", Float2Ty)
1690 .addParam("Bias", FloatTy)
1691 .addParam("Offset", Int2Ty)
1692 .addParam("Clamp", FloatTy)
1693 .accessHandleFieldOnResource(PH::_0)
1694 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1695 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1696 .returnValue(PH::LastStmt)
1697 .finalize();
1698}
1699
1702 assert(!Record->isCompleteDefinition() && "record is already complete");
1703 ASTContext &AST = Record->getASTContext();
1704 QualType ReturnType = getHandleElementType();
1705 QualType SamplerStateType =
1706 lookupBuiltinType(SemaRef, "SamplerState", 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 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy)
1715 BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1716 .addParam("Sampler", SamplerStateType)
1717 .addParam("Location", Float2Ty)
1718 .addParam("DDX", Float2Ty)
1719 .addParam("DDY", Float2Ty)
1720 .accessHandleFieldOnResource(PH::_0)
1721 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1722 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1723 .returnValue(PH::LastStmt)
1724 .finalize();
1725
1726 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy,
1727 // int2 offset)
1728 BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1729 .addParam("Sampler", SamplerStateType)
1730 .addParam("Location", Float2Ty)
1731 .addParam("DDX", Float2Ty)
1732 .addParam("DDY", Float2Ty)
1733 .addParam("Offset", Int2Ty)
1734 .accessHandleFieldOnResource(PH::_0)
1735 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1736 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1737 .returnValue(PH::LastStmt)
1738 .finalize();
1739
1740 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy,
1741 // int2 offset, float clamp)
1742 return BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1743 .addParam("Sampler", SamplerStateType)
1744 .addParam("Location", Float2Ty)
1745 .addParam("DDX", Float2Ty)
1746 .addParam("DDY", Float2Ty)
1747 .addParam("Offset", Int2Ty)
1748 .addParam("Clamp", FloatTy)
1749 .accessHandleFieldOnResource(PH::_0)
1750 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1751 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4,
1752 PH::_5)
1753 .returnValue(PH::LastStmt)
1754 .finalize();
1755}
1756
1759 assert(!Record->isCompleteDefinition() && "record is already complete");
1760 ASTContext &AST = Record->getASTContext();
1761 QualType ReturnType = getHandleElementType();
1762 QualType SamplerStateType =
1763 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1764 uint32_t VecSize = getResourceDimensions(Dim);
1765 QualType FloatTy = AST.FloatTy;
1766 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1767 QualType IntTy = AST.IntTy;
1768 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1769 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1770
1771 // T SampleLevel(SamplerState s, float2 location, float lod)
1772 BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
1773 .addParam("Sampler", SamplerStateType)
1774 .addParam("Location", Float2Ty)
1775 .addParam("LOD", FloatTy)
1776 .accessHandleFieldOnResource(PH::_0)
1777 .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
1778 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1779 .returnValue(PH::LastStmt)
1780 .finalize();
1781
1782 // T SampleLevel(SamplerState s, float2 location, float lod, int2 offset)
1783 return BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
1784 .addParam("Sampler", SamplerStateType)
1785 .addParam("Location", Float2Ty)
1786 .addParam("LOD", FloatTy)
1787 .addParam("Offset", Int2Ty)
1788 .accessHandleFieldOnResource(PH::_0)
1789 .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
1790 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1791 .returnValue(PH::LastStmt)
1792 .finalize();
1793}
1794
1797 assert(!Record->isCompleteDefinition() && "record is already complete");
1798 ASTContext &AST = Record->getASTContext();
1799 QualType ReturnType = AST.FloatTy;
1800 QualType SamplerComparisonStateType = lookupBuiltinType(
1801 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1802 uint32_t VecSize = getResourceDimensions(Dim);
1803 QualType FloatTy = AST.FloatTy;
1804 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1805 QualType IntTy = AST.IntTy;
1806 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1807 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1808
1809 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value)
1810 BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1811 .addParam("Sampler", SamplerComparisonStateType)
1812 .addParam("Location", Float2Ty)
1813 .addParam("CompareValue", FloatTy)
1814 .accessHandleFieldOnResource(PH::_0)
1815 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1816 PH::LastStmt, PH::_1, PH::_2)
1817 .returnValue(PH::LastStmt)
1818 .finalize();
1819
1820 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value,
1821 // int2 offset)
1822 BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1823 .addParam("Sampler", SamplerComparisonStateType)
1824 .addParam("Location", Float2Ty)
1825 .addParam("CompareValue", FloatTy)
1826 .addParam("Offset", Int2Ty)
1827 .accessHandleFieldOnResource(PH::_0)
1828 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1829 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1830 .returnValue(PH::LastStmt)
1831 .finalize();
1832
1833 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value,
1834 // int2 offset, float clamp)
1835 return BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1836 .addParam("Sampler", SamplerComparisonStateType)
1837 .addParam("Location", Float2Ty)
1838 .addParam("CompareValue", FloatTy)
1839 .addParam("Offset", Int2Ty)
1840 .addParam("Clamp", FloatTy)
1841 .accessHandleFieldOnResource(PH::_0)
1842 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1843 PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1844 .returnValue(PH::LastStmt)
1845 .finalize();
1846}
1847
1850 assert(!Record->isCompleteDefinition() && "record is already complete");
1851 ASTContext &AST = Record->getASTContext();
1852 QualType ReturnType = AST.FloatTy;
1853 QualType SamplerComparisonStateType = lookupBuiltinType(
1854 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1855 uint32_t VecSize = getResourceDimensions(Dim);
1856 QualType FloatTy = AST.FloatTy;
1857 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1858 QualType IntTy = AST.IntTy;
1859 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1860 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1861
1862 // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
1863 // compare_value)
1864 BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
1865 .addParam("Sampler", SamplerComparisonStateType)
1866 .addParam("Location", Float2Ty)
1867 .addParam("CompareValue", FloatTy)
1868 .accessHandleFieldOnResource(PH::_0)
1869 .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
1870 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1871 .returnValue(PH::LastStmt)
1872 .finalize();
1873
1874 // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
1875 // compare_value, int2 offset)
1876 return BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
1877 .addParam("Sampler", SamplerComparisonStateType)
1878 .addParam("Location", Float2Ty)
1879 .addParam("CompareValue", FloatTy)
1880 .addParam("Offset", Int2Ty)
1881 .accessHandleFieldOnResource(PH::_0)
1882 .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
1883 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1884 .returnValue(PH::LastStmt)
1885 .finalize();
1886}
1887
1890 assert(!Record->isCompleteDefinition() && "record is already complete");
1891 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1892 ASTContext &AST = SemaRef.getASTContext();
1893 QualType UIntTy = AST.UnsignedIntTy;
1894
1895 assert(Dim != ResourceDimension::Unknown);
1896
1897 QualType FloatTy = AST.FloatTy;
1898 // Add overloads for uint and float.
1899 QualType Params[] = {UIntTy, FloatTy};
1900
1901 for (QualType OutTy : Params) {
1902 if (Dim == ResourceDimension::Dim2D) {
1903 StringRef XYName = "__builtin_hlsl_resource_getdimensions_xy";
1904 StringRef LevelsXYName =
1905 "__builtin_hlsl_resource_getdimensions_levels_xy";
1906
1907 if (OutTy == FloatTy) {
1908 XYName = "__builtin_hlsl_resource_getdimensions_xy_float";
1909 LevelsXYName = "__builtin_hlsl_resource_getdimensions_levels_xy_float";
1910 }
1911
1912 // void GetDimensions(out [uint|float] width, out [uint|float] height)
1913 BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
1914 .addParam("width", OutTy, HLSLParamModifierAttr::Keyword_out)
1915 .addParam("height", OutTy, HLSLParamModifierAttr::Keyword_out)
1916 .callBuiltin(XYName, QualType(), PH::Handle, PH::_0, PH::_1)
1917 .finalize();
1918
1919 // void GetDimensions(uint mipLevel, out [uint|float] width, out
1920 // [uint|float] height, out [uint|float] numberOfLevels)
1921 BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
1922 .addParam("mipLevel", UIntTy)
1923 .addParam("width", OutTy, HLSLParamModifierAttr::Keyword_out)
1924 .addParam("height", OutTy, HLSLParamModifierAttr::Keyword_out)
1925 .addParam("numberOfLevels", OutTy, HLSLParamModifierAttr::Keyword_out)
1926 .callBuiltin(LevelsXYName, QualType(), PH::Handle, PH::_0, PH::_1,
1927 PH::_2, PH::_3)
1928 .finalize();
1929 }
1930 }
1931
1932 return *this;
1933}
1934
1937 assert(!Record->isCompleteDefinition() && "record is already complete");
1938 ASTContext &AST = Record->getASTContext();
1939 QualType ReturnType = AST.FloatTy;
1940 QualType SamplerStateType =
1941 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1942 uint32_t VecSize = getResourceDimensions(Dim);
1943 QualType FloatTy = AST.FloatTy;
1944 QualType LocationTy = AST.getExtVectorType(FloatTy, VecSize);
1945 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1946
1947 // float CalculateLevelOfDetail(SamplerState s, float2 location)
1948 BuiltinTypeMethodBuilder(*this, "CalculateLevelOfDetail", ReturnType)
1949 .addParam("Sampler", SamplerStateType)
1950 .addParam("Location", LocationTy)
1951 .accessHandleFieldOnResource(PH::_0)
1952 .callBuiltin("__builtin_hlsl_resource_calculate_lod", ReturnType,
1953 PH::Handle, PH::LastStmt, PH::_1)
1954 .finalize();
1955
1956 // float CalculateLevelOfDetailUnclamped(SamplerState s, float2 location)
1957 return BuiltinTypeMethodBuilder(*this, "CalculateLevelOfDetailUnclamped",
1958 ReturnType)
1959 .addParam("Sampler", SamplerStateType)
1960 .addParam("Location", LocationTy)
1961 .accessHandleFieldOnResource(PH::_0)
1962 .callBuiltin("__builtin_hlsl_resource_calculate_lod_unclamped",
1963 ReturnType, PH::Handle, PH::LastStmt, PH::_1)
1964 .finalize();
1965}
1966
1967QualType BuiltinTypeDeclBuilder::getGatherReturnType() {
1968 ASTContext &AST = SemaRef.getASTContext();
1969 QualType T = getHandleElementType();
1970 if (T.isNull())
1971 return QualType();
1972
1973 if (const auto *VT = T->getAs<VectorType>())
1974 T = VT->getElementType();
1975 else if (const auto *DT = T->getAs<DependentSizedExtVectorType>())
1976 T = DT->getElementType();
1977
1978 return AST.getExtVectorType(T, 4);
1979}
1980
1983 assert(!Record->isCompleteDefinition() && "record is already complete");
1984 ASTContext &AST = Record->getASTContext();
1985 QualType ReturnType = getGatherReturnType();
1986
1987 QualType SamplerStateType =
1988 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1989 uint32_t VecSize = getResourceDimensions(Dim);
1990 QualType LocationTy = AST.FloatTy;
1991 QualType Float2Ty = AST.getExtVectorType(LocationTy, VecSize);
1992 QualType IntTy = AST.IntTy;
1993 QualType OffsetTy = AST.getExtVectorType(IntTy, VecSize);
1994 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1995
1996 // Overloads for Gather, GatherRed, GatherGreen, GatherBlue, GatherAlpha
1997 struct GatherVariant {
1998 const char *Name;
1999 int Component;
2000 };
2001 GatherVariant Variants[] = {{"Gather", 0},
2002 {"GatherRed", 0},
2003 {"GatherGreen", 1},
2004 {"GatherBlue", 2},
2005 {"GatherAlpha", 3}};
2006
2007 for (const auto &V : Variants) {
2008 // ret GatherVariant(SamplerState s, float2 location)
2009 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2010 .addParam("Sampler", SamplerStateType)
2011 .addParam("Location", Float2Ty)
2012 .accessHandleFieldOnResource(PH::_0)
2013 .callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
2014 PH::LastStmt, PH::_1,
2015 getConstantUnsignedIntExpr(V.Component))
2016 .finalize();
2017
2018 // ret GatherVariant(SamplerState s, float2 location, int2 offset)
2019 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2020 .addParam("Sampler", SamplerStateType)
2021 .addParam("Location", Float2Ty)
2022 .addParam("Offset", OffsetTy)
2023 .accessHandleFieldOnResource(PH::_0)
2024 .callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
2025 PH::LastStmt, PH::_1,
2026 getConstantUnsignedIntExpr(V.Component), PH::_2)
2027 .finalize();
2028 }
2029
2030 return *this;
2031}
2032
2035 assert(!Record->isCompleteDefinition() && "record is already complete");
2036 ASTContext &AST = Record->getASTContext();
2037 QualType ReturnType = AST.getExtVectorType(AST.FloatTy, 4);
2038
2039 QualType SamplerComparisonStateType = lookupBuiltinType(
2040 SemaRef, "SamplerComparisonState", Record->getDeclContext());
2041 uint32_t VecSize = getResourceDimensions(Dim);
2042 QualType FloatTy = AST.FloatTy;
2043 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
2044 QualType IntTy = AST.IntTy;
2045 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
2046 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2047
2048 // Overloads for GatherCmp, GatherCmpRed, GatherCmpGreen, GatherCmpBlue,
2049 // GatherCmpAlpha
2050 struct GatherVariant {
2051 const char *Name;
2052 int Component;
2053 };
2054 GatherVariant Variants[] = {{"GatherCmp", 0},
2055 {"GatherCmpRed", 0},
2056 {"GatherCmpGreen", 1},
2057 {"GatherCmpBlue", 2},
2058 {"GatherCmpAlpha", 3}};
2059
2060 for (const auto &V : Variants) {
2061 // ret GatherCmpVariant(SamplerComparisonState s, float2 location, float
2062 // compare_value)
2063 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2064 .addParam("Sampler", SamplerComparisonStateType)
2065 .addParam("Location", Float2Ty)
2066 .addParam("CompareValue", FloatTy)
2067 .accessHandleFieldOnResource(PH::_0)
2068 .callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
2069 PH::Handle, PH::LastStmt, PH::_1, PH::_2,
2070 getConstantUnsignedIntExpr(V.Component))
2071 .finalize();
2072
2073 // ret GatherCmpVariant(SamplerComparisonState s, float2 location, float
2074 // compare_value, int2 offset)
2075 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2076 .addParam("Sampler", SamplerComparisonStateType)
2077 .addParam("Location", Float2Ty)
2078 .addParam("CompareValue", FloatTy)
2079 .addParam("Offset", Int2Ty)
2080 .accessHandleFieldOnResource(PH::_0)
2081 .callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
2082 PH::Handle, PH::LastStmt, PH::_1, PH::_2,
2083 getConstantUnsignedIntExpr(V.Component), PH::_3)
2084 .finalize();
2085 }
2086
2087 return *this;
2088}
2089
2090FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
2091 auto I = Fields.find("__handle");
2092 assert(I != Fields.end() &&
2093 I->second->getType()->isHLSLAttributedResourceType() &&
2094 "record does not have resource handle field");
2095 return I->second;
2096}
2097
2098FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField() const {
2099 auto I = Fields.find("__counter_handle");
2100 if (I == Fields.end() ||
2101 !I->second->getType()->isHLSLAttributedResourceType())
2102 return nullptr;
2103 return I->second;
2104}
2105
2106QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
2107 assert(Template && "record it not a template");
2108 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
2109 Template->getTemplateParameters()->getParam(0))) {
2110 return QualType(TTD->getTypeForDecl(), 0);
2111 }
2112 return QualType();
2113}
2114
2115QualType BuiltinTypeDeclBuilder::getHandleElementType() {
2116 if (Template)
2117 return getFirstTemplateTypeParam();
2118
2119 if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
2120 const auto &Args = Spec->getTemplateArgs();
2121 if (Args.size() > 0 && Args[0].getKind() == TemplateArgument::Type)
2122 return Args[0].getAsType();
2123 }
2124
2125 // TODO: Should we default to VoidTy? Using `i8` is arguably ambiguous.
2126 return SemaRef.getASTContext().Char8Ty;
2127}
2128
2129HLSLAttributedResourceType::Attributes
2130BuiltinTypeDeclBuilder::getResourceAttrs() const {
2131 QualType HandleType = getResourceHandleField()->getType();
2132 return cast<HLSLAttributedResourceType>(HandleType)->getAttrs();
2133}
2134
2136 assert(!Record->isCompleteDefinition() && "record is already complete");
2137 assert(Record->isBeingDefined() &&
2138 "Definition must be started before completing it.");
2139
2140 Record->completeDefinition();
2141 return *this;
2142}
2143
2144Expr *BuiltinTypeDeclBuilder::getConstantIntExpr(int value) {
2145 ASTContext &AST = SemaRef.getASTContext();
2147 AST, llvm::APInt(AST.getTypeSize(AST.IntTy), value, true), AST.IntTy,
2148 SourceLocation());
2149}
2150
2151Expr *BuiltinTypeDeclBuilder::getConstantUnsignedIntExpr(unsigned value) {
2152 ASTContext &AST = SemaRef.getASTContext();
2154 AST, llvm::APInt(AST.getTypeSize(AST.UnsignedIntTy), value),
2156}
2157
2163
2166 ArrayRef<QualType> DefaultTypes,
2167 ConceptDecl *CD) {
2168 if (Record->isCompleteDefinition()) {
2169 assert(Template && "existing record it not a template");
2170 assert(Template->getTemplateParameters()->size() == Names.size() &&
2171 "template param count mismatch");
2172 return *this;
2173 }
2174
2175 assert((DefaultTypes.empty() || DefaultTypes.size() == Names.size()) &&
2176 "template default argument count mismatch");
2177
2179 for (unsigned i = 0; i < Names.size(); ++i) {
2180 QualType DefaultTy = DefaultTypes.empty() ? QualType() : DefaultTypes[i];
2181 Builder.addTypeParameter(Names[i], DefaultTy);
2182 }
2183 return Builder.finalizeTemplateArgs(CD);
2184}
2185
2187 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2188 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
2189 return BuiltinTypeMethodBuilder(*this, "IncrementCounter", UnsignedIntTy)
2190 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
2191 PH::CounterHandle, getConstantIntExpr(1))
2192 .finalize();
2193}
2194
2196 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2197 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
2198 return BuiltinTypeMethodBuilder(*this, "DecrementCounter", UnsignedIntTy)
2199 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
2200 PH::CounterHandle, getConstantIntExpr(-1))
2201 .finalize();
2202}
2203
2205 DeclarationName &Name, bool IsConst, QualType ReturnTy) {
2206 assert(!Record->isCompleteDefinition() && "record is already complete");
2207 ASTContext &AST = SemaRef.getASTContext();
2208 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2209 bool NeedsTypedBuiltin = !ReturnTy.isNull();
2210
2211 // The empty QualType is a placeholder. The actual return type is set below.
2212 BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConst);
2213
2214 if (!NeedsTypedBuiltin)
2215 ReturnTy = getHandleElementType();
2216 if (ReturnTy == AST.DependentTy)
2217 ReturnTy = MMB.addTemplateTypeParam("element_type");
2218 MMB.ReturnTy = ReturnTy;
2219
2220 MMB.addParam("Index", AST.UnsignedIntTy)
2221 .addParam("Status", AST.UnsignedIntTy,
2222 HLSLParamModifierAttr::Keyword_out);
2223
2224 if (NeedsTypedBuiltin)
2225 MMB.callBuiltin("__builtin_hlsl_resource_load_with_status_typed", ReturnTy,
2226 PH::Handle, PH::_0, PH::_1, ReturnTy);
2227 else
2228 MMB.callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy,
2229 PH::Handle, PH::_0, PH::_1);
2230
2231 return MMB.finalize();
2232}
2233
2235 DeclarationName &Name, bool IsConst, bool IsRef, QualType IndexTy,
2236 QualType ElemTy) {
2237 assert(!Record->isCompleteDefinition() && "record is already complete");
2238 ASTContext &AST = SemaRef.getASTContext();
2239 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2240 bool NeedsTypedBuiltin = !ElemTy.isNull();
2241
2242 // The empty QualType is a placeholder. The actual return type is set below.
2243 BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConst);
2244
2245 if (!NeedsTypedBuiltin)
2246 ElemTy = getHandleElementType();
2247 if (ElemTy == AST.DependentTy)
2248 ElemTy = MMB.addTemplateTypeParam("element_type");
2249 QualType AddrSpaceElemTy =
2251 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
2252 QualType ReturnTy;
2253
2254 if (IsRef) {
2255 ReturnTy = AddrSpaceElemTy;
2256 if (IsConst)
2257 ReturnTy.addConst();
2258 ReturnTy = AST.getLValueReferenceType(ReturnTy);
2259 } else {
2260 ReturnTy = ElemTy;
2261 if (IsConst)
2262 ReturnTy.addConst();
2263 }
2264 MMB.ReturnTy = ReturnTy;
2265
2266 MMB.addParam("Index", IndexTy);
2267
2268 if (NeedsTypedBuiltin)
2269 MMB.callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
2270 PH::Handle, PH::_0, ElemTy);
2271 else
2272 MMB.callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
2273 PH::_0);
2274
2275 return MMB.dereference(PH::LastStmt).finalize();
2276}
2277
2280 QualType ValueTy) {
2281 assert(!Record->isCompleteDefinition() && "record is already complete");
2282 ASTContext &AST = SemaRef.getASTContext();
2283 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2284
2285 BuiltinTypeMethodBuilder MMB(*this, Name, AST.VoidTy, IsConst);
2286
2287 if (ValueTy == AST.DependentTy)
2288 ValueTy = MMB.addTemplateTypeParam("element_type");
2289 QualType AddrSpaceElemTy =
2291 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
2292
2293 return MMB.addParam("Index", AST.UnsignedIntTy)
2294 .addParam("Value", ValueTy)
2295 .callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
2296 PH::Handle, PH::_0, ValueTy)
2297 .dereference(PH::LastStmt)
2298 .assign(PH::LastStmt, PH::_1)
2299 .finalize();
2300}
2301
2303 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2304 ASTContext &AST = SemaRef.getASTContext();
2305 QualType ElemTy = getHandleElementType();
2306 QualType AddrSpaceElemTy =
2308 return BuiltinTypeMethodBuilder(*this, "Append", AST.VoidTy)
2309 .addParam("value", ElemTy)
2310 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
2311 PH::CounterHandle, getConstantIntExpr(1))
2312 .callBuiltin("__builtin_hlsl_resource_getpointer",
2313 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
2314 PH::LastStmt)
2315 .dereference(PH::LastStmt)
2316 .assign(PH::LastStmt, PH::_0)
2317 .finalize();
2318}
2319
2321 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2322 ASTContext &AST = SemaRef.getASTContext();
2323 QualType ElemTy = getHandleElementType();
2324 QualType AddrSpaceElemTy =
2326 return BuiltinTypeMethodBuilder(*this, "Consume", ElemTy)
2327 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
2328 PH::CounterHandle, getConstantIntExpr(-1))
2329 .callBuiltin("__builtin_hlsl_resource_getpointer",
2330 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
2331 PH::LastStmt)
2332 .dereference(PH::LastStmt)
2333 .finalize();
2334}
2335
2338 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2339 ASTContext &AST = SemaRef.getASTContext();
2340 QualType UIntTy = AST.UnsignedIntTy;
2341
2342 QualType HandleTy = getResourceHandleField()->getType();
2343 auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr());
2344
2345 // Structured buffers except {RW}ByteAddressBuffer have overload
2346 // GetDimensions(out uint numStructs, out uint stride).
2347 if (AttrResTy->getAttrs().RawBuffer &&
2348 AttrResTy->getContainedType() != AST.Char8Ty) {
2349 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
2350 .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out)
2351 .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out)
2352 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
2353 PH::Handle, PH::_0)
2354 .callBuiltin("__builtin_hlsl_resource_getstride", QualType(),
2355 PH::Handle, PH::_1)
2356 .finalize();
2357 }
2358
2359 // Typed buffers and {RW}ByteAddressBuffer have overload
2360 // GetDimensions(out uint dim).
2361 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
2362 .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out)
2363 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
2364 PH::Handle, PH::_0)
2365 .finalize();
2366}
2367
2368} // namespace hlsl
2369} // 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.
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
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
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents a member of a struct/union/class.
Definition Decl.h:3175
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
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2724
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:1182
Represents a C++ constructor within a class.
Definition DeclCXX.h:2624
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:3020
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:1158
static CXXThisExpr * Create(const ASTContext &Ctx, SourceLocation L, QualType Ty, bool IsImplicit)
Definition ExprCXX.cpp:1587
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:1462
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:1637
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void setAccess(AccessSpecifier AS)
Definition DeclBase.h:510
void setImplicit(bool I=true)
Definition DeclBase.h:602
void setLexicalDeclContext(DeclContext *DC)
Definition DeclBase.cpp:386
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
void setType(QualType t)
Definition Expr.h:145
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:4702
FriendDecl - Represents the declaration of a friend entity, which can be a function,...
Definition DeclFriend.h:54
static FriendDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, SourceLocation FriendL, SourceLocation EllipsisLoc={}, ArrayRef< TemplateParameterList * > FriendTypeTPLists={})
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)
Describes an C or C++ initializer list.
Definition Expr.h:5302
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.
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:2959
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
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:1141
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9415
@ LookupTagName
Tag name lookup, which finds the names of enums, classes, structs, and unions.
Definition Sema.h:9418
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
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9328
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:754
bool isVectorType() const
Definition TypeBase.h:8807
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:2164
Represents a GCC generic vector type.
Definition TypeBase.h:4225
BuiltinTypeDeclBuilder & addStoreFunction(DeclarationName &Name, bool IsConst, QualType ValueType)
BuiltinTypeDeclBuilder & addDefaultHandleConstructor(AccessSpecifier Access=AccessSpecifier::AS_public)
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 & addCopyAssignmentOperator(AccessSpecifier Access=AccessSpecifier::AS_public)
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 & addCopyConstructor(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeDeclBuilder & addTextureLoadMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addSampleLevelMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addMipsMember(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addByteAddressBufferLoadMethods()
BuiltinTypeDeclBuilder & addSampleMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addStaticInitializationFunctions(bool HasCounter)
BuiltinTypeDeclBuilder & addCalculateLodMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addGetDimensionsMethods(ResourceDimension Dim)
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
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ ICIS_NoInit
No in-class initializer.
Definition Specifiers.h:273
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:152
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition Specifiers.h:124
@ AS_public
Definition Specifiers.h:125
@ AS_protected
Definition Specifiers.h:126
@ AS_private
Definition Specifiers.h:127
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
Definition Specifiers.h:249
@ SC_Static
Definition Specifiers.h:253
@ SC_None
Definition Specifiers.h:251
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:381
@ 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:136
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
Definition Specifiers.h:145
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:140
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 & concat(V Vec, S Scalar, QualType ResultTy)
BuiltinTypeMethodBuilder & addParam(StringRef Name, QualType Ty, HLSLParamModifierAttr::Spelling Modifier=HLSLParamModifierAttr::Keyword_in)
BuiltinTypeMethodBuilder & accessFieldOnResource(T ResourceRecord, FieldDecl *Field)
BuiltinTypeDeclBuilder & finalize(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeMethodBuilder & callBuiltin(StringRef BuiltinName, QualType ReturnType, Ts &&...ArgSpecs)
BuiltinTypeMethodBuilder & accessHandleFieldOnResource(T ResourceRecord)
BuiltinTypeMethodBuilder & setHandleFieldOnResource(LocalVar &ResourceRecord, ValueT HandleValue)
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 & setFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue, FieldDecl *HandleField)
BuiltinTypeMethodBuilder & setCounterHandleFieldOnResource(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)