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,
559 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo,
560 false, /*isInline=*/true, ExplicitSpecifier(),
561 ConstexprSpecKind::Unspecified, SourceLocation());
562 else
563 Method = CXXMethodDecl::Create(
564 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo, SC,
565 false, true, ConstexprSpecKind::Unspecified, SourceLocation());
566
567 // Create params & set them to the method/constructor and function prototype.
569 unsigned CurScopeDepth = DeclBuilder.SemaRef.getCurScope()->getDepth();
570 auto FnProtoLoc =
571 Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
572 for (int I = 0, E = Params.size(); I != E; I++) {
573 Param &MP = Params[I];
574 ParmVarDecl *Parm = ParmVarDecl::Create(
575 AST, Method, SourceLocation(), SourceLocation(), &MP.NameII, MP.Ty,
576 AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None,
577 nullptr);
578 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
579 auto *Mod =
580 HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
581 Parm->addAttr(Mod);
582 }
583 Parm->setScopeInfo(CurScopeDepth, I);
584 ParmDecls.push_back(Parm);
585 FnProtoLoc.setParam(I, Parm);
586 }
587 Method->setParams({ParmDecls});
588}
589
591 ensureCompleteDecl();
592
593 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
595 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
596 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
597 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
598 HandleField->getType(), VK_LValue,
600}
601
603 ensureCompleteDecl();
604
605 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
607 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
608 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
609 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
610 HandleField->getType(), VK_LValue,
612}
613
616 ensureCompleteDecl();
617
618 assert(Var.Decl == nullptr && "local variable is already declared");
619
620 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
621 Var.Decl = VarDecl::Create(
622 AST, Method, SourceLocation(), SourceLocation(),
623 &AST.Idents.get(Var.Name, tok::TokenKind::identifier), Var.Ty,
625 DeclStmt *DS = new (AST) clang::DeclStmt(DeclGroupRef(Var.Decl),
627 StmtsList.push_back(DS);
628 return *this;
629}
630
631template <typename V, typename S>
633 QualType ResultTy) {
634 assert(ResultTy->isVectorType() && "The result type must be a vector type.");
635 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
636 Expr *VecExpr = convertPlaceholder(Vec);
637 auto *VecTy = VecExpr->getType()->castAs<VectorType>();
638 Expr *ScalarExpr = convertPlaceholder(Scalar);
639
640 // Save the vector to a local variable to avoid evaluating the placeholder
641 // multiple times or sharing the AST node.
642 LocalVar VecVar("vec_tmp", VecTy->desugar());
643 declareLocalVar(VecVar);
644 assign(VecVar, VecExpr);
645
646 QualType EltTy = VecTy->getElementType();
647 unsigned NumElts = VecTy->getNumElements();
648
650 for (unsigned I = 0; I < NumElts; ++I) {
651 Elts.push_back(new (AST) ArraySubscriptExpr(
652 convertPlaceholder(VecVar), DeclBuilder.getConstantIntExpr(I), EltTy,
654 }
655 Elts.push_back(ScalarExpr);
656
657 auto *InitList =
658 new (AST) InitListExpr(AST, SourceLocation(), Elts, SourceLocation());
659 InitList->setType(ResultTy);
660
661 ExprResult Cast = DeclBuilder.SemaRef.BuildCStyleCastExpr(
663 SourceLocation(), InitList);
664 assert(!Cast.isInvalid() && "Cast cannot fail!");
665 StmtsList.push_back(Cast.get());
666
667 return *this;
668}
669
671 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
673 AST, SourceLocation(), Method->getFunctionObjectParameterType(),
674 /*IsImplicit=*/true);
675 StmtsList.push_back(ThisExpr);
676 return *this;
677}
678
679template <typename... Ts>
682 QualType ReturnType, Ts &&...ArgSpecs) {
683 ensureCompleteDecl();
684
685 std::array<Expr *, sizeof...(ArgSpecs)> Args{
686 convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
687
688 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
689 FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
691 AST, NestedNameSpecifierLoc(), SourceLocation(), FD, false,
693
694 ExprResult Call = DeclBuilder.SemaRef.BuildCallExpr(
695 /*Scope=*/nullptr, DRE, SourceLocation(),
696 MultiExprArg(Args.data(), Args.size()), SourceLocation());
697 assert(!Call.isInvalid() && "Call to builtin cannot fail!");
698 Expr *E = Call.get();
699
700 if (!ReturnType.isNull() &&
701 !AST.hasSameUnqualifiedType(ReturnType, E->getType())) {
702 ExprResult CastResult = DeclBuilder.SemaRef.BuildCStyleCastExpr(
703 SourceLocation(), AST.getTrivialTypeSourceInfo(ReturnType),
704 SourceLocation(), E);
705 assert(!CastResult.isInvalid() && "Cast cannot fail!");
706 E = CastResult.get();
707 }
708
709 StmtsList.push_back(E);
710 return *this;
711}
712
713template <typename TLHS, typename TRHS>
715 Expr *LHSExpr = convertPlaceholder(LHS);
716 Expr *RHSExpr = convertPlaceholder(RHS);
717 Stmt *AssignStmt = BinaryOperator::Create(
718 DeclBuilder.SemaRef.getASTContext(), LHSExpr, RHSExpr, BO_Assign,
721 StmtsList.push_back(AssignStmt);
722 return *this;
723}
724
725template <typename T>
727 Expr *PtrExpr = convertPlaceholder(Ptr);
728 Expr *Deref =
729 UnaryOperator::Create(DeclBuilder.SemaRef.getASTContext(), PtrExpr,
730 UO_Deref, PtrExpr->getType()->getPointeeType(),
732 /*CanOverflow=*/false, FPOptionsOverride());
733 StmtsList.push_back(Deref);
734 return *this;
735}
736
737template <typename T>
740 ensureCompleteDecl();
741
742 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
743 auto *ResourceTypeDecl = ResourceExpr->getType()->getAsCXXRecordDecl();
744
745 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
746 FieldDecl *HandleField = nullptr;
747
748 if (ResourceTypeDecl == DeclBuilder.Record)
749 HandleField = DeclBuilder.getResourceHandleField();
750 else {
751 IdentifierInfo &II = AST.Idents.get("__handle");
752 for (auto *Decl : ResourceTypeDecl->lookup(&II)) {
753 if ((HandleField = dyn_cast<FieldDecl>(Decl)))
754 break;
755 }
756 assert(HandleField && "Resource handle field not found");
757 }
758
760 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
762 StmtsList.push_back(HandleExpr);
763 return *this;
764}
765
766template <typename T>
769 FieldDecl *Field) {
770 ensureCompleteDecl();
771 Expr *Base = convertPlaceholder(ResourceRecord);
772
773 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
774 auto *Member =
775 MemberExpr::CreateImplicit(AST, Base, /*IsArrow=*/false, Field,
776 Field->getType(), VK_LValue, OK_Ordinary);
777 StmtsList.push_back(Member);
778 return *this;
779}
780
781void BuiltinTypeMethodBuilder::setMipsHandleField(LocalVar &ResourceRecord) {
782 FieldDecl *MipsField = DeclBuilder.Fields.lookup("mips");
783 if (!MipsField)
784 return;
785
786 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
787 QualType MipsTy = MipsField->getType();
788 const auto *RT = MipsTy->castAs<RecordType>();
789 CXXRecordDecl *MipsRecord = cast<CXXRecordDecl>(RT->getDecl());
790
791 // The mips record should have a single field that is the handle.
792 assert(MipsRecord->field_begin() != MipsRecord->field_end() &&
793 "mips_type must have at least one field");
794 assert(std::next(MipsRecord->field_begin()) == MipsRecord->field_end() &&
795 "mips_type must have exactly one field");
796 FieldDecl *MipsHandleField = *MipsRecord->field_begin();
797
798 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
799 Expr *ResExpr = convertPlaceholder(ResourceRecord);
800 MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
801 AST, ResExpr, false, HandleField, HandleField->getType(), VK_LValue,
803
804 MemberExpr *MipsMemberExpr =
805 MemberExpr::CreateImplicit(AST, ResExpr, false, MipsField,
806 MipsField->getType(), VK_LValue, OK_Ordinary);
807 MemberExpr *MipsHandleMemberExpr = MemberExpr::CreateImplicit(
808 AST, MipsMemberExpr, false, MipsHandleField, MipsHandleField->getType(),
810
811 Stmt *AssignStmt = BinaryOperator::Create(
812 AST, MipsHandleMemberExpr, HandleMemberExpr, BO_Assign,
813 MipsHandleMemberExpr->getType(), ExprValueKind::VK_LValue,
815
816 StmtsList.push_back(AssignStmt);
817}
818
819template <typename ValueT>
822 ValueT HandleValue) {
823 setFieldOnResource(ResourceRecord, HandleValue,
824 DeclBuilder.getResourceHandleField());
825 setMipsHandleField(ResourceRecord);
826 return *this;
827}
828
829template <typename ResourceT, typename ValueT>
832 ResourceT ResourceRecord, ValueT HandleValue) {
833 return setFieldOnResource(ResourceRecord, HandleValue,
834 DeclBuilder.getResourceCounterHandleField());
835}
836
837template <typename ResourceT, typename ValueT>
839 ResourceT ResourceRecord, ValueT HandleValue, FieldDecl *HandleField) {
840 ensureCompleteDecl();
841
842 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
843 assert(ResourceExpr->getType()->getAsCXXRecordDecl() ==
844 HandleField->getParent() &&
845 "Getting the field from the wrong resource type.");
846
847 Expr *HandleValueExpr = convertPlaceholder(HandleValue);
848
849 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
850 MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
851 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
853 Stmt *AssignStmt = BinaryOperator::Create(
854 DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr,
855 BO_Assign, HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
857 StmtsList.push_back(AssignStmt);
858 return *this;
859}
860
861template <typename T>
864 ensureCompleteDecl();
865
866 Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
867 assert(ResourceExpr->getType()->getAsCXXRecordDecl() == DeclBuilder.Record &&
868 "Getting the field from the wrong resource type.");
869
870 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
871 FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
873 AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
875 StmtsList.push_back(HandleExpr);
876 return *this;
877}
878
879template <typename T>
881 ensureCompleteDecl();
882
883 Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
884 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
885
886 QualType Ty = ReturnValueExpr->getType();
887 if (Ty->isRecordType() && !Method->getReturnType()->isReferenceType()) {
888 // For record types, create a call to copy constructor to ensure proper copy
889 // semantics.
890 auto *ICE =
891 ImplicitCastExpr::Create(AST, Ty.withConst(), CK_NoOp, ReturnValueExpr,
892 nullptr, VK_XValue, FPOptionsOverride());
893 CXXConstructorDecl *CD = lookupCopyConstructor(Ty);
894 assert(CD && "no copy constructor found");
895 ReturnValueExpr = CXXConstructExpr::Create(
896 AST, Ty, SourceLocation(), CD, /*Elidable=*/false, {ICE},
897 /*HadMultipleCandidates=*/false, /*ListInitialization=*/false,
898 /*StdInitListInitialization=*/false,
899 /*ZeroInitListInitialization=*/false, CXXConstructionKind::Complete,
900 SourceRange());
901 }
902 StmtsList.push_back(
903 ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr));
904 return *this;
905}
906
909 assert(!DeclBuilder.Record->isCompleteDefinition() &&
910 "record is already complete");
911
912 ensureCompleteDecl();
913
914 if (!Method->hasBody()) {
915 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
916 assert((ReturnTy == AST.VoidTy || !StmtsList.empty()) &&
917 "nothing to return from non-void method");
918 if (ReturnTy != AST.VoidTy) {
919 if (Expr *LastExpr = dyn_cast<Expr>(StmtsList.back())) {
920 assert(AST.hasSameUnqualifiedType(LastExpr->getType(),
921 ReturnTy.getNonReferenceType()) &&
922 "Return type of the last statement must match the return type "
923 "of the method");
924 if (!isa<ReturnStmt>(LastExpr)) {
925 StmtsList.pop_back();
926 StmtsList.push_back(
927 ReturnStmt::Create(AST, SourceLocation(), LastExpr, nullptr));
928 }
929 }
930 }
931
932 Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
934 Method->setLexicalDeclContext(DeclBuilder.Record);
935 Method->setAccess(Access);
936 Method->setImplicitlyInline();
937 Method->addAttr(AlwaysInlineAttr::CreateImplicit(
938 AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
939 Method->addAttr(ConvergentAttr::CreateImplicit(AST));
940 if (!TemplateParamDecls.empty()) {
941 TemplateParams = TemplateParameterList::Create(
942 AST, SourceLocation(), SourceLocation(), TemplateParamDecls,
943 SourceLocation(), nullptr);
944
945 auto *FuncTemplate = FunctionTemplateDecl::Create(AST, DeclBuilder.Record,
946 SourceLocation(), Name,
947 TemplateParams, Method);
948 FuncTemplate->setAccess(AS_public);
949 FuncTemplate->setLexicalDeclContext(DeclBuilder.Record);
950 FuncTemplate->setImplicit(true);
951 Method->setDescribedFunctionTemplate(FuncTemplate);
952 DeclBuilder.Record->addDecl(FuncTemplate);
953 } else {
954 DeclBuilder.Record->addDecl(Method);
955 }
956 }
957 return DeclBuilder;
958}
959
961 : SemaRef(SemaRef), Record(R) {
962 Record->startDefinition();
963 Template = Record->getDescribedClassTemplate();
964}
965
967 NamespaceDecl *Namespace,
968 StringRef Name)
969 : SemaRef(SemaRef), HLSLNamespace(Namespace) {
970 ASTContext &AST = SemaRef.getASTContext();
971 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
972
974 CXXRecordDecl *PrevDecl = nullptr;
975 if (SemaRef.LookupQualifiedName(Result, HLSLNamespace)) {
976 // Declaration already exists (from precompiled headers)
977 NamedDecl *Found = Result.getFoundDecl();
978 if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
979 PrevDecl = TD->getTemplatedDecl();
980 PrevTemplate = TD;
981 } else
982 PrevDecl = dyn_cast<CXXRecordDecl>(Found);
983 assert(PrevDecl && "Unexpected lookup result type.");
984 }
985
986 if (PrevDecl && PrevDecl->isCompleteDefinition()) {
987 Record = PrevDecl;
988 Template = PrevTemplate;
989 return;
990 }
991
992 Record =
993 CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
994 SourceLocation(), SourceLocation(), &II, PrevDecl);
995 Record->setImplicit(true);
996 Record->setLexicalDeclContext(HLSLNamespace);
997 Record->setHasExternalLexicalStorage();
998
999 // Don't let anyone derive from built-in types.
1000 Record->addAttr(
1001 FinalAttr::CreateImplicit(AST, SourceRange(), FinalAttr::Keyword_final));
1002}
1003
1005 if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
1006 HLSLNamespace->addDecl(Record);
1007}
1008
1012 AccessSpecifier Access) {
1013 assert(!Record->isCompleteDefinition() && "record is already complete");
1014 assert(Record->isBeingDefined() &&
1015 "Definition must be started before adding members!");
1016 ASTContext &AST = Record->getASTContext();
1017
1018 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
1019 TypeSourceInfo *MemTySource =
1021 auto *Field = FieldDecl::Create(
1022 AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
1023 nullptr, false, InClassInitStyle::ICIS_NoInit);
1024 Field->setAccess(Access);
1025 Field->setImplicit(true);
1026 for (Attr *A : Attrs) {
1027 if (A)
1028 Field->addAttr(A);
1029 }
1030
1031 Record->addDecl(Field);
1032 Fields[Name] = Field;
1033 return *this;
1034}
1035
1037BuiltinTypeDeclBuilder::addBufferHandles(ResourceClass RC, bool IsROV,
1038 bool RawBuffer, bool HasCounter,
1039 AccessSpecifier Access) {
1040 QualType ElementTy = getHandleElementType();
1041 addHandleMember(RC, ResourceDimension::Unknown, IsROV, RawBuffer, ElementTy,
1042 Access);
1043 if (HasCounter)
1044 addCounterHandleMember(RC, IsROV, RawBuffer, ElementTy, Access);
1045 return *this;
1046}
1047
1049BuiltinTypeDeclBuilder::addTextureHandle(ResourceClass RC, bool IsROV,
1050 ResourceDimension RD,
1051 AccessSpecifier Access) {
1052 addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, getHandleElementType(),
1053 Access);
1054 return *this;
1055}
1056
1058 addHandleMember(ResourceClass::Sampler, ResourceDimension::Unknown,
1059 /*IsROV=*/false, /*RawBuffer=*/false, getHandleElementType());
1060 return *this;
1061}
1062
1065 assert(!Record->isCompleteDefinition() && "record is already complete");
1066 ASTContext &AST = SemaRef.getASTContext();
1067 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1068
1069 QualType ElemTy = getHandleElementType();
1070 QualType AddrSpaceElemTy = AST.getCanonicalType(
1072 QualType ReturnTy =
1073 AST.getCanonicalType(AST.getLValueReferenceType(AddrSpaceElemTy));
1074
1076 AST.getCanonicalType(ReturnTy));
1077
1078 return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, /*IsConst=*/true)
1079 .callBuiltin("__builtin_hlsl_resource_getpointer",
1080 AST.getPointerType(AddrSpaceElemTy), PH::Handle)
1081 .dereference(PH::LastStmt)
1082 .finalize();
1083}
1084
1086BuiltinTypeDeclBuilder::addFriend(CXXRecordDecl *Friend) {
1087 assert(!Record->isCompleteDefinition() && "record is already complete");
1088 ASTContext &AST = SemaRef.getASTContext();
1089 QualType FriendTy = AST.getCanonicalTagType(Friend);
1090 TypeSourceInfo *TSI = AST.getTrivialTypeSourceInfo(FriendTy);
1091 FriendDecl *FD =
1093 FD->setAccess(AS_public);
1094 Record->addDecl(FD);
1095 return *this;
1096}
1097
1098CXXRecordDecl *BuiltinTypeDeclBuilder::addPrivateNestedRecord(StringRef Name) {
1099 assert(!Record->isCompleteDefinition() && "record is already complete");
1100 ASTContext &AST = SemaRef.getASTContext();
1101 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
1102 CXXRecordDecl *NestedRecord =
1103 CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, Record,
1104 SourceLocation(), SourceLocation(), &II);
1105 NestedRecord->setImplicit(true);
1107 NestedRecord->setLexicalDeclContext(Record);
1108 Record->addDecl(NestedRecord);
1109 return NestedRecord;
1110}
1111
1112BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
1113 ResourceClass RC, ResourceDimension RD, bool IsROV, bool RawBuffer,
1114 QualType ElementTy, AccessSpecifier Access) {
1115 return addResourceMember("__handle", RC, RD, IsROV, RawBuffer,
1116 /*IsCounter=*/false, ElementTy, Access);
1117}
1118
1119BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
1120 ResourceClass RC, bool IsROV, bool RawBuffer, QualType ElementTy,
1121 AccessSpecifier Access) {
1122 return addResourceMember("__counter_handle", RC, ResourceDimension::Unknown,
1123 IsROV, RawBuffer,
1124 /*IsCounter=*/true, ElementTy, Access);
1125}
1126
1127BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember(
1128 StringRef MemberName, ResourceClass RC, ResourceDimension RD, bool IsROV,
1129 bool RawBuffer, bool IsCounter, QualType ElementTy,
1130 AccessSpecifier Access) {
1131 assert(!Record->isCompleteDefinition() && "record is already complete");
1132
1133 ASTContext &Ctx = SemaRef.getASTContext();
1134
1135 assert(!ElementTy.isNull() &&
1136 "The caller should always pass in the type for the handle.");
1137 TypeSourceInfo *ElementTypeInfo =
1138 Ctx.getTrivialTypeSourceInfo(ElementTy, SourceLocation());
1139
1140 // add handle member with resource type attributes
1141 QualType AttributedResTy = QualType();
1142 SmallVector<const Attr *> Attrs = {
1143 HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
1144 IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
1145 RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
1146 RD != ResourceDimension::Unknown
1147 ? HLSLResourceDimensionAttr::CreateImplicit(Ctx, RD)
1148 : nullptr,
1149 ElementTypeInfo && RC != ResourceClass::Sampler
1150 ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
1151 : nullptr};
1152 if (IsCounter)
1153 Attrs.push_back(HLSLIsCounterAttr::CreateImplicit(Ctx));
1154
1155 if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
1156 AttributedResTy))
1157 addMemberVariable(MemberName, AttributedResTy, {}, Access);
1158 return *this;
1159}
1160
1161// Adds default constructor to the resource class:
1162// Resource::Resource()
1165 assert(!Record->isCompleteDefinition() && "record is already complete");
1166
1167 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1168 QualType HandleType = getResourceHandleField()->getType();
1169 return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
1170 false, true)
1171 .callBuiltin("__builtin_hlsl_resource_uninitializedhandle", HandleType,
1172 PH::Handle)
1173 .assign(PH::Handle, PH::LastStmt)
1174 .finalize(Access);
1175}
1176
1179 if (HasCounter) {
1180 addCreateFromBindingWithImplicitCounter();
1181 addCreateFromImplicitBindingWithImplicitCounter();
1182 } else {
1183 addCreateFromBinding();
1184 addCreateFromImplicitBinding();
1185 }
1186 return *this;
1187}
1188
1189// Adds static method that initializes resource from binding:
1190//
1191// static Resource<T> __createFromBinding(unsigned registerNo,
1192// unsigned spaceNo, int range,
1193// unsigned index, const char *name) {
1194// Resource<T> tmp;
1195// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1196// tmp.__handle, registerNo, spaceNo,
1197// range, index, name);
1198// return tmp;
1199// }
1200BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
1201 assert(!Record->isCompleteDefinition() && "record is already complete");
1202
1203 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1204 ASTContext &AST = SemaRef.getASTContext();
1205 QualType HandleType = getResourceHandleField()->getType();
1206 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1207 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1208
1209 return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
1210 false, false, SC_Static)
1211 .addParam("registerNo", AST.UnsignedIntTy)
1212 .addParam("spaceNo", AST.UnsignedIntTy)
1213 .addParam("range", AST.IntTy)
1214 .addParam("index", AST.UnsignedIntTy)
1215 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1216 .declareLocalVar(TmpVar)
1217 .accessHandleFieldOnResource(TmpVar)
1218 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1219 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1220 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1221 .returnValue(TmpVar)
1222 .finalize();
1223}
1224
1225// Adds static method that initializes resource from binding:
1226//
1227// static Resource<T> __createFromImplicitBinding(unsigned orderId,
1228// unsigned spaceNo, int range,
1229// unsigned index,
1230// const char *name) {
1231// Resource<T> tmp;
1232// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1233// tmp.__handle, spaceNo,
1234// range, index, orderId, name);
1235// return tmp;
1236// }
1237BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
1238 assert(!Record->isCompleteDefinition() && "record is already complete");
1239
1240 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1241 ASTContext &AST = SemaRef.getASTContext();
1242 QualType HandleType = getResourceHandleField()->getType();
1243 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1244 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1245
1246 return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
1247 RecordType, false, false, SC_Static)
1248 .addParam("orderId", AST.UnsignedIntTy)
1249 .addParam("spaceNo", AST.UnsignedIntTy)
1250 .addParam("range", AST.IntTy)
1251 .addParam("index", AST.UnsignedIntTy)
1252 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1253 .declareLocalVar(TmpVar)
1254 .accessHandleFieldOnResource(TmpVar)
1255 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1256 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1257 PH::_4)
1258 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1259 .returnValue(TmpVar)
1260 .finalize();
1261}
1262
1263// Adds static method that initializes resource from binding:
1264//
1265// static Resource<T>
1266// __createFromBindingWithImplicitCounter(unsigned registerNo,
1267// unsigned spaceNo, int range,
1268// unsigned index, const char *name,
1269// unsigned counterOrderId) {
1270// Resource<T> tmp;
1271// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1272// tmp.__handle, registerNo, spaceNo, range, index, name);
1273// tmp.__counter_handle =
1274// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1275// tmp.__handle, counterOrderId, spaceNo);
1276// return tmp;
1277// }
1279BuiltinTypeDeclBuilder::addCreateFromBindingWithImplicitCounter() {
1280 assert(!Record->isCompleteDefinition() && "record is already complete");
1281
1282 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1283 ASTContext &AST = SemaRef.getASTContext();
1284 QualType HandleType = getResourceHandleField()->getType();
1285 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1286 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1287 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1288
1289 return BuiltinTypeMethodBuilder(*this,
1290 "__createFromBindingWithImplicitCounter",
1291 RecordType, false, false, SC_Static)
1292 .addParam("registerNo", AST.UnsignedIntTy)
1293 .addParam("spaceNo", AST.UnsignedIntTy)
1294 .addParam("range", AST.IntTy)
1295 .addParam("index", AST.UnsignedIntTy)
1296 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1297 .addParam("counterOrderId", AST.UnsignedIntTy)
1298 .declareLocalVar(TmpVar)
1299 .accessHandleFieldOnResource(TmpVar)
1300 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1301 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1302 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1303 .accessHandleFieldOnResource(TmpVar)
1304 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1305 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1306 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1307 .returnValue(TmpVar)
1308 .finalize();
1309}
1310
1311// Adds static method that initializes resource from binding:
1312//
1313// static Resource<T>
1314// __createFromImplicitBindingWithImplicitCounter(unsigned orderId,
1315// unsigned spaceNo, int range,
1316// unsigned index,
1317// const char *name,
1318// unsigned counterOrderId) {
1319// Resource<T> tmp;
1320// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1321// tmp.__handle, orderId, spaceNo, range, index, name);
1322// tmp.__counter_handle =
1323// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1324// tmp.__handle, counterOrderId, spaceNo);
1325// return tmp;
1326// }
1328BuiltinTypeDeclBuilder::addCreateFromImplicitBindingWithImplicitCounter() {
1329 assert(!Record->isCompleteDefinition() && "record is already complete");
1330
1331 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1332 ASTContext &AST = SemaRef.getASTContext();
1333 QualType HandleType = getResourceHandleField()->getType();
1334 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1335 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1336 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1337
1339 *this, "__createFromImplicitBindingWithImplicitCounter",
1340 RecordType, false, false, SC_Static)
1341 .addParam("orderId", AST.UnsignedIntTy)
1342 .addParam("spaceNo", AST.UnsignedIntTy)
1343 .addParam("range", AST.IntTy)
1344 .addParam("index", AST.UnsignedIntTy)
1345 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1346 .addParam("counterOrderId", AST.UnsignedIntTy)
1347 .declareLocalVar(TmpVar)
1348 .accessHandleFieldOnResource(TmpVar)
1349 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1350 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1351 PH::_4)
1352 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1353 .accessHandleFieldOnResource(TmpVar)
1354 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1355 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1356 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1357 .returnValue(TmpVar)
1358 .finalize();
1359}
1360
1363 assert(!Record->isCompleteDefinition() && "record is already complete");
1364
1365 ASTContext &AST = SemaRef.getASTContext();
1366 QualType RecordType = AST.getCanonicalTagType(Record);
1367 QualType ConstRecordType = RecordType.withConst();
1368 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1369
1370 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1371
1372 BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy,
1373 /*IsConst=*/false, /*IsCtor=*/true);
1374 MMB.addParam("other", ConstRecordRefType);
1375
1376 for (auto *Field : Record->fields()) {
1377 MMB.accessFieldOnResource(PH::_0, Field)
1378 .setFieldOnResource(PH::This, PH::LastStmt, Field);
1379 }
1380
1381 return MMB.finalize(Access);
1382}
1383
1386 assert(!Record->isCompleteDefinition() && "record is already complete");
1387
1388 ASTContext &AST = SemaRef.getASTContext();
1389 QualType RecordType = AST.getCanonicalTagType(Record);
1390 QualType ConstRecordType = RecordType.withConst();
1391 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1392 QualType RecordRefType = AST.getLValueReferenceType(RecordType);
1393
1394 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1396 BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType);
1397 MMB.addParam("other", ConstRecordRefType);
1398
1399 for (auto *Field : Record->fields()) {
1400 MMB.accessFieldOnResource(PH::_0, Field)
1401 .setFieldOnResource(PH::This, PH::LastStmt, Field);
1402 }
1403
1404 return MMB.returnThis().finalize(Access);
1405}
1406
1409 assert(!Record->isCompleteDefinition() && "record is already complete");
1410 ASTContext &AST = Record->getASTContext();
1411
1412 uint32_t VecSize = 1;
1413 if (Dim != ResourceDimension::Unknown)
1414 VecSize = getResourceDimensions(Dim);
1415
1416 QualType IndexTy = VecSize > 1
1417 ? AST.getExtVectorType(AST.UnsignedIntTy, VecSize)
1418 : AST.UnsignedIntTy;
1419
1420 DeclarationName Subscript =
1421 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1422
1423 addHandleAccessFunction(Subscript,
1424 /*IsConstReturn=*/getResourceAttrs().ResourceClass !=
1425 llvm::dxil::ResourceClass::UAV,
1426 /*IsRef=*/true, IndexTy);
1427
1428 return *this;
1429}
1430
1432 assert(!Record->isCompleteDefinition() && "record is already complete");
1433
1434 ASTContext &AST = Record->getASTContext();
1435 IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
1436 DeclarationName Load(&II);
1437
1439 /*IsConstReturn=*/false, /*IsRef=*/false,
1440 AST.UnsignedIntTy);
1442
1443 return *this;
1444}
1445
1446CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsSliceType(ResourceDimension Dim,
1447 QualType ReturnType) {
1448 ASTContext &AST = Record->getASTContext();
1449 uint32_t VecSize = getResourceDimensions(Dim);
1450 QualType IntTy = AST.IntTy;
1451 QualType IndexTy = VecSize > 1 ? AST.getExtVectorType(IntTy, VecSize) : IntTy;
1452 QualType CoordLevelTy = AST.getExtVectorType(IntTy, VecSize + 1);
1453 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1454
1455 // Define the mips_slice_type which is returned by mips_type::operator[].
1456 // It holds the resource handle and the mip level. It has an operator[]
1457 // that takes the coordinate and performs the actual resource load.
1458 CXXRecordDecl *MipsSliceRecord = addPrivateNestedRecord("mips_slice_type");
1459 BuiltinTypeDeclBuilder MipsSliceBuilder(SemaRef, MipsSliceRecord);
1460 MipsSliceBuilder.addFriend(Record)
1461 .addHandleMember(getResourceAttrs().ResourceClass, Dim,
1462 getResourceAttrs().IsROV, false, ReturnType,
1464 .addMemberVariable("__level", IntTy, {}, AccessSpecifier::AS_public)
1468
1469 FieldDecl *LevelField = MipsSliceBuilder.Fields["__level"];
1470 assert(LevelField && "Could not find the level field.");
1471
1472 DeclarationName SubscriptName =
1473 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1474
1475 // operator[](intN coord) on mips_slice_type
1476 BuiltinTypeMethodBuilder(MipsSliceBuilder, SubscriptName, ReturnType,
1477 /*IsConst=*/true)
1478 .addParam("Coord", IndexTy)
1479 .accessFieldOnResource(PH::This, LevelField)
1480 .concat(PH::_0, PH::LastStmt, CoordLevelTy)
1481 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1482 PH::LastStmt)
1483 .finalize();
1484
1485 MipsSliceBuilder.completeDefinition();
1486 return MipsSliceRecord;
1487}
1488
1489CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsType(ResourceDimension Dim,
1490 QualType ReturnType) {
1491 ASTContext &AST = Record->getASTContext();
1492 QualType IntTy = AST.IntTy;
1493 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1494
1495 // First, define the mips_slice_type that will be returned by our operator[].
1496 CXXRecordDecl *MipsSliceRecord = addMipsSliceType(Dim, ReturnType);
1497
1498 // Define the mips_type, which provides the syntax `Resource.mips[level]`.
1499 // It only holds the handle, and its operator[] returns a mips_slice_type
1500 // initialized with the handle and the requested mip level.
1501 CXXRecordDecl *MipsRecord = addPrivateNestedRecord("mips_type");
1502 BuiltinTypeDeclBuilder MipsBuilder(SemaRef, MipsRecord);
1503 MipsBuilder.addFriend(Record)
1504 .addHandleMember(getResourceAttrs().ResourceClass, Dim,
1505 getResourceAttrs().IsROV, false, ReturnType,
1507 .addDefaultHandleConstructor(AccessSpecifier::AS_protected)
1508 .addCopyConstructor(AccessSpecifier::AS_protected)
1509 .addCopyAssignmentOperator(AccessSpecifier::AS_protected);
1510
1511 QualType MipsSliceTy = AST.getCanonicalTagType(MipsSliceRecord);
1512
1513 DeclarationName SubscriptName =
1514 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1515
1516 // Locate the fields in the slice type so we can initialize them.
1517 auto FieldIt = MipsSliceRecord->field_begin();
1518 FieldDecl *MipsSliceHandleField = *FieldIt;
1519 FieldDecl *LevelField = *++FieldIt;
1520 assert(MipsSliceHandleField->getName() == "__handle" &&
1521 LevelField->getName() == "__level" &&
1522 "Could not find fields on mips_slice_type");
1523
1524 // operator[](int level) on mips_type
1525 BuiltinTypeMethodBuilder::LocalVar MipsSliceVar("slice", MipsSliceTy);
1526 BuiltinTypeMethodBuilder(MipsBuilder, SubscriptName, MipsSliceTy,
1527 /*IsConst=*/true)
1528 .addParam("Level", IntTy)
1529 .declareLocalVar(MipsSliceVar)
1530 .accessHandleFieldOnResource(PH::This)
1531 .setFieldOnResource(MipsSliceVar, PH::LastStmt, MipsSliceHandleField)
1532 .setFieldOnResource(MipsSliceVar, PH::_0, LevelField)
1533 .returnValue(MipsSliceVar)
1534 .finalize();
1535
1536 MipsBuilder.completeDefinition();
1537 return MipsRecord;
1538}
1539
1542 assert(!Record->isCompleteDefinition() && "record is already complete");
1543 ASTContext &AST = Record->getASTContext();
1544 QualType ReturnType = getHandleElementType();
1545
1546 CXXRecordDecl *MipsRecord = addMipsType(Dim, ReturnType);
1547
1548 // Add the mips field to the texture
1549 QualType MipsTy = AST.getCanonicalTagType(MipsRecord);
1550 addMemberVariable("mips", MipsTy, {}, AccessSpecifier::AS_public);
1551
1552 return *this;
1553}
1554
1557 assert(!Record->isCompleteDefinition() && "record is already complete");
1558 ASTContext &AST = Record->getASTContext();
1559 uint32_t VecSize = getResourceDimensions(Dim);
1560 QualType IntTy = AST.IntTy;
1561 QualType OffsetTy = AST.getExtVectorType(IntTy, VecSize);
1562 QualType LocationTy = AST.getExtVectorType(IntTy, VecSize + 1);
1563 QualType ReturnType = getHandleElementType();
1564
1565 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1566
1567 // T Load(int3 location)
1568 BuiltinTypeMethodBuilder(*this, "Load", ReturnType)
1569 .addParam("Location", LocationTy)
1570 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1571 PH::_0)
1572 .finalize();
1573
1574 // T Load(int3 location, int2 offset)
1575 return BuiltinTypeMethodBuilder(*this, "Load", ReturnType)
1576 .addParam("Location", LocationTy)
1577 .addParam("Offset", OffsetTy)
1578 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1579 PH::_0, PH::_1)
1580 .finalize();
1581}
1582
1585 assert(!Record->isCompleteDefinition() && "record is already complete");
1586
1587 ASTContext &AST = SemaRef.getASTContext();
1588
1589 auto AddLoads = [&](StringRef MethodName, QualType ReturnType) {
1590 IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
1591 DeclarationName Load(&II);
1592
1594 /*IsConstReturn=*/false, /*IsRef=*/false,
1595 AST.UnsignedIntTy, ReturnType);
1596 addLoadWithStatusFunction(Load, ReturnType);
1597 };
1598
1599 AddLoads("Load", AST.UnsignedIntTy);
1600 AddLoads("Load2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
1601 AddLoads("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
1602 AddLoads("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
1603 AddLoads("Load", AST.DependentTy); // Templated version
1604 return *this;
1605}
1606
1609 assert(!Record->isCompleteDefinition() && "record is already complete");
1610
1611 ASTContext &AST = SemaRef.getASTContext();
1612
1613 auto AddStore = [&](StringRef MethodName, QualType ValueType) {
1614 IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
1615 DeclarationName Store(&II);
1616
1617 addStoreFunction(Store, /*IsConst=*/false, ValueType);
1618 };
1619
1620 AddStore("Store", AST.UnsignedIntTy);
1621 AddStore("Store2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
1622 AddStore("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
1623 AddStore("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
1624 AddStore("Store", AST.DependentTy); // Templated version
1625
1626 return *this;
1627}
1628
1631 assert(!Record->isCompleteDefinition() && "record is already complete");
1632 ASTContext &AST = Record->getASTContext();
1633 QualType ReturnType = getHandleElementType();
1634 QualType SamplerStateType =
1635 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1636 uint32_t VecSize = getResourceDimensions(Dim);
1637 QualType FloatTy = AST.FloatTy;
1638 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1639 QualType IntTy = AST.IntTy;
1640 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1641 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1642
1643 // T Sample(SamplerState s, float2 location)
1644 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1645 .addParam("Sampler", SamplerStateType)
1646 .addParam("Location", Float2Ty)
1647 .accessHandleFieldOnResource(PH::_0)
1648 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1649 PH::LastStmt, PH::_1)
1650 .returnValue(PH::LastStmt)
1651 .finalize();
1652
1653 // T Sample(SamplerState s, float2 location, int2 offset)
1654 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1655 .addParam("Sampler", SamplerStateType)
1656 .addParam("Location", Float2Ty)
1657 .addParam("Offset", Int2Ty)
1658 .accessHandleFieldOnResource(PH::_0)
1659 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1660 PH::LastStmt, PH::_1, PH::_2)
1661 .returnValue(PH::LastStmt)
1662 .finalize();
1663
1664 // T Sample(SamplerState s, float2 location, int2 offset, float clamp)
1665 return BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1666 .addParam("Sampler", SamplerStateType)
1667 .addParam("Location", Float2Ty)
1668 .addParam("Offset", Int2Ty)
1669 .addParam("Clamp", FloatTy)
1670 .accessHandleFieldOnResource(PH::_0)
1671 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1672 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1673 .returnValue(PH::LastStmt)
1674 .finalize();
1675}
1676
1679 assert(!Record->isCompleteDefinition() && "record is already complete");
1680 ASTContext &AST = Record->getASTContext();
1681 QualType ReturnType = getHandleElementType();
1682 QualType SamplerStateType =
1683 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1684 uint32_t VecSize = getResourceDimensions(Dim);
1685 QualType FloatTy = AST.FloatTy;
1686 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1687 QualType IntTy = AST.IntTy;
1688 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1689 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1690
1691 // T SampleBias(SamplerState s, float2 location, float bias)
1692 BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1693 .addParam("Sampler", SamplerStateType)
1694 .addParam("Location", Float2Ty)
1695 .addParam("Bias", FloatTy)
1696 .accessHandleFieldOnResource(PH::_0)
1697 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1698 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1699 .returnValue(PH::LastStmt)
1700 .finalize();
1701
1702 // T SampleBias(SamplerState s, float2 location, float bias, int2 offset)
1703 BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1704 .addParam("Sampler", SamplerStateType)
1705 .addParam("Location", Float2Ty)
1706 .addParam("Bias", FloatTy)
1707 .addParam("Offset", Int2Ty)
1708 .accessHandleFieldOnResource(PH::_0)
1709 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1710 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1711 .returnValue(PH::LastStmt)
1712 .finalize();
1713
1714 // T SampleBias(SamplerState s, float2 location, float bias, int2 offset,
1715 // float clamp)
1716 return BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1717 .addParam("Sampler", SamplerStateType)
1718 .addParam("Location", Float2Ty)
1719 .addParam("Bias", FloatTy)
1720 .addParam("Offset", Int2Ty)
1721 .addParam("Clamp", FloatTy)
1722 .accessHandleFieldOnResource(PH::_0)
1723 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1724 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1725 .returnValue(PH::LastStmt)
1726 .finalize();
1727}
1728
1731 assert(!Record->isCompleteDefinition() && "record is already complete");
1732 ASTContext &AST = Record->getASTContext();
1733 QualType ReturnType = getHandleElementType();
1734 QualType SamplerStateType =
1735 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1736 uint32_t VecSize = getResourceDimensions(Dim);
1737 QualType FloatTy = AST.FloatTy;
1738 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1739 QualType IntTy = AST.IntTy;
1740 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1741 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1742
1743 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy)
1744 BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1745 .addParam("Sampler", SamplerStateType)
1746 .addParam("Location", Float2Ty)
1747 .addParam("DDX", Float2Ty)
1748 .addParam("DDY", Float2Ty)
1749 .accessHandleFieldOnResource(PH::_0)
1750 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1751 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1752 .returnValue(PH::LastStmt)
1753 .finalize();
1754
1755 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy,
1756 // int2 offset)
1757 BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1758 .addParam("Sampler", SamplerStateType)
1759 .addParam("Location", Float2Ty)
1760 .addParam("DDX", Float2Ty)
1761 .addParam("DDY", Float2Ty)
1762 .addParam("Offset", Int2Ty)
1763 .accessHandleFieldOnResource(PH::_0)
1764 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1765 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1766 .returnValue(PH::LastStmt)
1767 .finalize();
1768
1769 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy,
1770 // int2 offset, float clamp)
1771 return BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1772 .addParam("Sampler", SamplerStateType)
1773 .addParam("Location", Float2Ty)
1774 .addParam("DDX", Float2Ty)
1775 .addParam("DDY", Float2Ty)
1776 .addParam("Offset", Int2Ty)
1777 .addParam("Clamp", FloatTy)
1778 .accessHandleFieldOnResource(PH::_0)
1779 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1780 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4,
1781 PH::_5)
1782 .returnValue(PH::LastStmt)
1783 .finalize();
1784}
1785
1788 assert(!Record->isCompleteDefinition() && "record is already complete");
1789 ASTContext &AST = Record->getASTContext();
1790 QualType ReturnType = getHandleElementType();
1791 QualType SamplerStateType =
1792 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1793 uint32_t VecSize = getResourceDimensions(Dim);
1794 QualType FloatTy = AST.FloatTy;
1795 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1796 QualType IntTy = AST.IntTy;
1797 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1798 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1799
1800 // T SampleLevel(SamplerState s, float2 location, float lod)
1801 BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
1802 .addParam("Sampler", SamplerStateType)
1803 .addParam("Location", Float2Ty)
1804 .addParam("LOD", FloatTy)
1805 .accessHandleFieldOnResource(PH::_0)
1806 .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
1807 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1808 .returnValue(PH::LastStmt)
1809 .finalize();
1810
1811 // T SampleLevel(SamplerState s, float2 location, float lod, int2 offset)
1812 return BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
1813 .addParam("Sampler", SamplerStateType)
1814 .addParam("Location", Float2Ty)
1815 .addParam("LOD", FloatTy)
1816 .addParam("Offset", Int2Ty)
1817 .accessHandleFieldOnResource(PH::_0)
1818 .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
1819 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1820 .returnValue(PH::LastStmt)
1821 .finalize();
1822}
1823
1826 assert(!Record->isCompleteDefinition() && "record is already complete");
1827 ASTContext &AST = Record->getASTContext();
1828 QualType ReturnType = AST.FloatTy;
1829 QualType SamplerComparisonStateType = lookupBuiltinType(
1830 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1831 uint32_t VecSize = getResourceDimensions(Dim);
1832 QualType FloatTy = AST.FloatTy;
1833 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1834 QualType IntTy = AST.IntTy;
1835 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1836 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1837
1838 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value)
1839 BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1840 .addParam("Sampler", SamplerComparisonStateType)
1841 .addParam("Location", Float2Ty)
1842 .addParam("CompareValue", FloatTy)
1843 .accessHandleFieldOnResource(PH::_0)
1844 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1845 PH::LastStmt, PH::_1, PH::_2)
1846 .returnValue(PH::LastStmt)
1847 .finalize();
1848
1849 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value,
1850 // int2 offset)
1851 BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1852 .addParam("Sampler", SamplerComparisonStateType)
1853 .addParam("Location", Float2Ty)
1854 .addParam("CompareValue", FloatTy)
1855 .addParam("Offset", Int2Ty)
1856 .accessHandleFieldOnResource(PH::_0)
1857 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1858 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1859 .returnValue(PH::LastStmt)
1860 .finalize();
1861
1862 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value,
1863 // int2 offset, float clamp)
1864 return BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1865 .addParam("Sampler", SamplerComparisonStateType)
1866 .addParam("Location", Float2Ty)
1867 .addParam("CompareValue", FloatTy)
1868 .addParam("Offset", Int2Ty)
1869 .addParam("Clamp", FloatTy)
1870 .accessHandleFieldOnResource(PH::_0)
1871 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1872 PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1873 .returnValue(PH::LastStmt)
1874 .finalize();
1875}
1876
1879 assert(!Record->isCompleteDefinition() && "record is already complete");
1880 ASTContext &AST = Record->getASTContext();
1881 QualType ReturnType = AST.FloatTy;
1882 QualType SamplerComparisonStateType = lookupBuiltinType(
1883 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1884 uint32_t VecSize = getResourceDimensions(Dim);
1885 QualType FloatTy = AST.FloatTy;
1886 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
1887 QualType IntTy = AST.IntTy;
1888 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
1889 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1890
1891 // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
1892 // compare_value)
1893 BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
1894 .addParam("Sampler", SamplerComparisonStateType)
1895 .addParam("Location", Float2Ty)
1896 .addParam("CompareValue", FloatTy)
1897 .accessHandleFieldOnResource(PH::_0)
1898 .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
1899 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1900 .returnValue(PH::LastStmt)
1901 .finalize();
1902
1903 // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
1904 // compare_value, int2 offset)
1905 return BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
1906 .addParam("Sampler", SamplerComparisonStateType)
1907 .addParam("Location", Float2Ty)
1908 .addParam("CompareValue", FloatTy)
1909 .addParam("Offset", Int2Ty)
1910 .accessHandleFieldOnResource(PH::_0)
1911 .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
1912 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1913 .returnValue(PH::LastStmt)
1914 .finalize();
1915}
1916
1919 assert(!Record->isCompleteDefinition() && "record is already complete");
1920 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1921 ASTContext &AST = SemaRef.getASTContext();
1922 QualType UIntTy = AST.UnsignedIntTy;
1923
1924 assert(Dim != ResourceDimension::Unknown);
1925
1926 QualType FloatTy = AST.FloatTy;
1927 // Add overloads for uint and float.
1928 QualType Params[] = {UIntTy, FloatTy};
1929
1930 for (QualType OutTy : Params) {
1931 if (Dim == ResourceDimension::Dim2D) {
1932 StringRef XYName = "__builtin_hlsl_resource_getdimensions_xy";
1933 StringRef LevelsXYName =
1934 "__builtin_hlsl_resource_getdimensions_levels_xy";
1935
1936 if (OutTy == FloatTy) {
1937 XYName = "__builtin_hlsl_resource_getdimensions_xy_float";
1938 LevelsXYName = "__builtin_hlsl_resource_getdimensions_levels_xy_float";
1939 }
1940
1941 // void GetDimensions(out [uint|float] width, out [uint|float] height)
1942 BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
1943 .addParam("width", OutTy, HLSLParamModifierAttr::Keyword_out)
1944 .addParam("height", OutTy, HLSLParamModifierAttr::Keyword_out)
1945 .callBuiltin(XYName, QualType(), PH::Handle, PH::_0, PH::_1)
1946 .finalize();
1947
1948 // void GetDimensions(uint mipLevel, out [uint|float] width, out
1949 // [uint|float] height, out [uint|float] numberOfLevels)
1950 BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
1951 .addParam("mipLevel", UIntTy)
1952 .addParam("width", OutTy, HLSLParamModifierAttr::Keyword_out)
1953 .addParam("height", OutTy, HLSLParamModifierAttr::Keyword_out)
1954 .addParam("numberOfLevels", OutTy, HLSLParamModifierAttr::Keyword_out)
1955 .callBuiltin(LevelsXYName, QualType(), PH::Handle, PH::_0, PH::_1,
1956 PH::_2, PH::_3)
1957 .finalize();
1958 }
1959 }
1960
1961 return *this;
1962}
1963
1966 assert(!Record->isCompleteDefinition() && "record is already complete");
1967 ASTContext &AST = Record->getASTContext();
1968 QualType ReturnType = AST.FloatTy;
1969 QualType SamplerStateType =
1970 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1971 uint32_t VecSize = getResourceDimensions(Dim);
1972 QualType FloatTy = AST.FloatTy;
1973 QualType LocationTy = AST.getExtVectorType(FloatTy, VecSize);
1974 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1975
1976 // float CalculateLevelOfDetail(SamplerState s, float2 location)
1977 BuiltinTypeMethodBuilder(*this, "CalculateLevelOfDetail", ReturnType)
1978 .addParam("Sampler", SamplerStateType)
1979 .addParam("Location", LocationTy)
1980 .accessHandleFieldOnResource(PH::_0)
1981 .callBuiltin("__builtin_hlsl_resource_calculate_lod", ReturnType,
1982 PH::Handle, PH::LastStmt, PH::_1)
1983 .finalize();
1984
1985 // float CalculateLevelOfDetailUnclamped(SamplerState s, float2 location)
1986 return BuiltinTypeMethodBuilder(*this, "CalculateLevelOfDetailUnclamped",
1987 ReturnType)
1988 .addParam("Sampler", SamplerStateType)
1989 .addParam("Location", LocationTy)
1990 .accessHandleFieldOnResource(PH::_0)
1991 .callBuiltin("__builtin_hlsl_resource_calculate_lod_unclamped",
1992 ReturnType, PH::Handle, PH::LastStmt, PH::_1)
1993 .finalize();
1994}
1995
1996QualType BuiltinTypeDeclBuilder::getGatherReturnType() {
1997 ASTContext &AST = SemaRef.getASTContext();
1998 QualType T = getHandleElementType();
1999 if (T.isNull())
2000 return QualType();
2001
2002 if (const auto *VT = T->getAs<VectorType>())
2003 T = VT->getElementType();
2004 else if (const auto *DT = T->getAs<DependentSizedExtVectorType>())
2005 T = DT->getElementType();
2006
2007 return AST.getExtVectorType(T, 4);
2008}
2009
2012 assert(!Record->isCompleteDefinition() && "record is already complete");
2013 ASTContext &AST = Record->getASTContext();
2014 QualType ReturnType = getGatherReturnType();
2015
2016 QualType SamplerStateType =
2017 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
2018 uint32_t VecSize = getResourceDimensions(Dim);
2019 QualType LocationTy = AST.FloatTy;
2020 QualType Float2Ty = AST.getExtVectorType(LocationTy, VecSize);
2021 QualType IntTy = AST.IntTy;
2022 QualType OffsetTy = AST.getExtVectorType(IntTy, VecSize);
2023 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2024
2025 // Overloads for Gather, GatherRed, GatherGreen, GatherBlue, GatherAlpha
2026 struct GatherVariant {
2027 const char *Name;
2028 int Component;
2029 };
2030 GatherVariant Variants[] = {{"Gather", 0},
2031 {"GatherRed", 0},
2032 {"GatherGreen", 1},
2033 {"GatherBlue", 2},
2034 {"GatherAlpha", 3}};
2035
2036 for (const auto &V : Variants) {
2037 // ret GatherVariant(SamplerState s, float2 location)
2038 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2039 .addParam("Sampler", SamplerStateType)
2040 .addParam("Location", Float2Ty)
2041 .accessHandleFieldOnResource(PH::_0)
2042 .callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
2043 PH::LastStmt, PH::_1,
2044 getConstantUnsignedIntExpr(V.Component))
2045 .finalize();
2046
2047 // ret GatherVariant(SamplerState s, float2 location, int2 offset)
2048 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2049 .addParam("Sampler", SamplerStateType)
2050 .addParam("Location", Float2Ty)
2051 .addParam("Offset", OffsetTy)
2052 .accessHandleFieldOnResource(PH::_0)
2053 .callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
2054 PH::LastStmt, PH::_1,
2055 getConstantUnsignedIntExpr(V.Component), PH::_2)
2056 .finalize();
2057 }
2058
2059 return *this;
2060}
2061
2064 assert(!Record->isCompleteDefinition() && "record is already complete");
2065 ASTContext &AST = Record->getASTContext();
2066 QualType ReturnType = AST.getExtVectorType(AST.FloatTy, 4);
2067
2068 QualType SamplerComparisonStateType = lookupBuiltinType(
2069 SemaRef, "SamplerComparisonState", Record->getDeclContext());
2070 uint32_t VecSize = getResourceDimensions(Dim);
2071 QualType FloatTy = AST.FloatTy;
2072 QualType Float2Ty = AST.getExtVectorType(FloatTy, VecSize);
2073 QualType IntTy = AST.IntTy;
2074 QualType Int2Ty = AST.getExtVectorType(IntTy, VecSize);
2075 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2076
2077 // Overloads for GatherCmp, GatherCmpRed, GatherCmpGreen, GatherCmpBlue,
2078 // GatherCmpAlpha
2079 struct GatherVariant {
2080 const char *Name;
2081 int Component;
2082 };
2083 GatherVariant Variants[] = {{"GatherCmp", 0},
2084 {"GatherCmpRed", 0},
2085 {"GatherCmpGreen", 1},
2086 {"GatherCmpBlue", 2},
2087 {"GatherCmpAlpha", 3}};
2088
2089 for (const auto &V : Variants) {
2090 // ret GatherCmpVariant(SamplerComparisonState s, float2 location, float
2091 // compare_value)
2092 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2093 .addParam("Sampler", SamplerComparisonStateType)
2094 .addParam("Location", Float2Ty)
2095 .addParam("CompareValue", FloatTy)
2096 .accessHandleFieldOnResource(PH::_0)
2097 .callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
2098 PH::Handle, PH::LastStmt, PH::_1, PH::_2,
2099 getConstantUnsignedIntExpr(V.Component))
2100 .finalize();
2101
2102 // ret GatherCmpVariant(SamplerComparisonState s, float2 location, float
2103 // compare_value, int2 offset)
2104 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2105 .addParam("Sampler", SamplerComparisonStateType)
2106 .addParam("Location", Float2Ty)
2107 .addParam("CompareValue", FloatTy)
2108 .addParam("Offset", Int2Ty)
2109 .accessHandleFieldOnResource(PH::_0)
2110 .callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
2111 PH::Handle, PH::LastStmt, PH::_1, PH::_2,
2112 getConstantUnsignedIntExpr(V.Component), PH::_3)
2113 .finalize();
2114 }
2115
2116 return *this;
2117}
2118
2119FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
2120 auto I = Fields.find("__handle");
2121 assert(I != Fields.end() &&
2122 I->second->getType()->isHLSLAttributedResourceType() &&
2123 "record does not have resource handle field");
2124 return I->second;
2125}
2126
2127FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField() const {
2128 auto I = Fields.find("__counter_handle");
2129 if (I == Fields.end() ||
2130 !I->second->getType()->isHLSLAttributedResourceType())
2131 return nullptr;
2132 return I->second;
2133}
2134
2135QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
2136 assert(Template && "record it not a template");
2137 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
2138 Template->getTemplateParameters()->getParam(0))) {
2139 return QualType(TTD->getTypeForDecl(), 0);
2140 }
2141 return QualType();
2142}
2143
2144QualType BuiltinTypeDeclBuilder::getHandleElementType() {
2145 if (Template)
2146 return getFirstTemplateTypeParam();
2147
2148 if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
2149 const auto &Args = Spec->getTemplateArgs();
2150 if (Args.size() > 0 && Args[0].getKind() == TemplateArgument::Type)
2151 return Args[0].getAsType();
2152 }
2153
2154 // TODO: Should we default to VoidTy? Using `i8` is arguably ambiguous.
2155 return SemaRef.getASTContext().Char8Ty;
2156}
2157
2158HLSLAttributedResourceType::Attributes
2159BuiltinTypeDeclBuilder::getResourceAttrs() const {
2160 QualType HandleType = getResourceHandleField()->getType();
2161 return cast<HLSLAttributedResourceType>(HandleType)->getAttrs();
2162}
2163
2165 assert(!Record->isCompleteDefinition() && "record is already complete");
2166 assert(Record->isBeingDefined() &&
2167 "Definition must be started before completing it.");
2168
2169 Record->completeDefinition();
2170 return *this;
2171}
2172
2173Expr *BuiltinTypeDeclBuilder::getConstantIntExpr(int value) {
2174 ASTContext &AST = SemaRef.getASTContext();
2176 AST, llvm::APInt(AST.getTypeSize(AST.IntTy), value, true), AST.IntTy,
2177 SourceLocation());
2178}
2179
2180Expr *BuiltinTypeDeclBuilder::getConstantUnsignedIntExpr(unsigned value) {
2181 ASTContext &AST = SemaRef.getASTContext();
2183 AST, llvm::APInt(AST.getTypeSize(AST.UnsignedIntTy), value),
2185}
2186
2192
2195 ArrayRef<QualType> DefaultTypes,
2196 ConceptDecl *CD) {
2197 if (Record->isCompleteDefinition()) {
2198 assert(Template && "existing record it not a template");
2199 assert(Template->getTemplateParameters()->size() == Names.size() &&
2200 "template param count mismatch");
2201 return *this;
2202 }
2203
2204 assert((DefaultTypes.empty() || DefaultTypes.size() == Names.size()) &&
2205 "template default argument count mismatch");
2206
2208 for (unsigned i = 0; i < Names.size(); ++i) {
2209 QualType DefaultTy = DefaultTypes.empty() ? QualType() : DefaultTypes[i];
2210 Builder.addTypeParameter(Names[i], DefaultTy);
2211 }
2212 return Builder.finalizeTemplateArgs(CD);
2213}
2214
2216 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2217 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
2218 return BuiltinTypeMethodBuilder(*this, "IncrementCounter", UnsignedIntTy)
2219 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
2220 PH::CounterHandle, getConstantIntExpr(1))
2221 .finalize();
2222}
2223
2225 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2226 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
2227 return BuiltinTypeMethodBuilder(*this, "DecrementCounter", UnsignedIntTy)
2228 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
2229 PH::CounterHandle, getConstantIntExpr(-1))
2230 .finalize();
2231}
2232
2235 QualType ReturnTy) {
2236 assert(!Record->isCompleteDefinition() && "record is already complete");
2237 ASTContext &AST = SemaRef.getASTContext();
2238 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2239 bool NeedsTypedBuiltin = !ReturnTy.isNull();
2240
2241 // The empty QualType is a placeholder. The actual return type is set below.
2242 // All load methods will be const.
2243 BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), true);
2244
2245 if (!NeedsTypedBuiltin)
2246 ReturnTy = getHandleElementType();
2247 if (ReturnTy == AST.DependentTy)
2248 ReturnTy = MMB.addTemplateTypeParam("element_type");
2249 MMB.ReturnTy = ReturnTy;
2250
2251 MMB.addParam("Index", AST.UnsignedIntTy)
2252 .addParam("Status", AST.UnsignedIntTy,
2253 HLSLParamModifierAttr::Keyword_out);
2254
2255 if (NeedsTypedBuiltin)
2256 MMB.callBuiltin("__builtin_hlsl_resource_load_with_status_typed", ReturnTy,
2257 PH::Handle, PH::_0, PH::_1, ReturnTy);
2258 else
2259 MMB.callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy,
2260 PH::Handle, PH::_0, PH::_1);
2261
2262 return MMB.finalize();
2263}
2264
2266 DeclarationName &Name, bool IsConstReturn, bool IsRef, QualType IndexTy,
2267 QualType ElemTy) {
2268 assert(!Record->isCompleteDefinition() && "record is already complete");
2269 ASTContext &AST = SemaRef.getASTContext();
2270 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2271 bool NeedsTypedBuiltin = !ElemTy.isNull();
2272
2273 // The empty QualType is a placeholder. The actual return type is set below.
2274 // All access methods are const; none of them rebind the resource handle.
2275 BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), true);
2276
2277 if (!NeedsTypedBuiltin)
2278 ElemTy = getHandleElementType();
2279 if (ElemTy == AST.DependentTy)
2280 ElemTy = MMB.addTemplateTypeParam("element_type");
2281 QualType AddrSpaceElemTy =
2283 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
2284 QualType ReturnTy;
2285
2286 if (IsRef) {
2287 ReturnTy = AddrSpaceElemTy;
2288 if (IsConstReturn)
2289 ReturnTy.addConst();
2290 ReturnTy = AST.getLValueReferenceType(ReturnTy);
2291 } else {
2292 assert(!IsConstReturn && "There shouldn't be any resource methods with a "
2293 "const ref return value");
2294 ReturnTy = ElemTy;
2295 }
2296 MMB.ReturnTy = ReturnTy;
2297
2298 MMB.addParam("Index", IndexTy);
2299
2300 if (NeedsTypedBuiltin)
2301 MMB.callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
2302 PH::Handle, PH::_0, ElemTy);
2303 else
2304 MMB.callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
2305 PH::_0);
2306
2307 return MMB.dereference(PH::LastStmt).finalize();
2308}
2309
2312 QualType ValueTy) {
2313 assert(!Record->isCompleteDefinition() && "record is already complete");
2314 ASTContext &AST = SemaRef.getASTContext();
2315 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2316
2317 BuiltinTypeMethodBuilder MMB(*this, Name, AST.VoidTy, IsConst);
2318
2319 if (ValueTy == AST.DependentTy)
2320 ValueTy = MMB.addTemplateTypeParam("element_type");
2321 QualType AddrSpaceElemTy =
2323 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
2324
2325 return MMB.addParam("Index", AST.UnsignedIntTy)
2326 .addParam("Value", ValueTy)
2327 .callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
2328 PH::Handle, PH::_0, ValueTy)
2329 .dereference(PH::LastStmt)
2330 .assign(PH::LastStmt, PH::_1)
2331 .finalize();
2332}
2333
2335 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2336 ASTContext &AST = SemaRef.getASTContext();
2337 QualType ElemTy = getHandleElementType();
2338 QualType AddrSpaceElemTy =
2340 return BuiltinTypeMethodBuilder(*this, "Append", AST.VoidTy)
2341 .addParam("value", ElemTy)
2342 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
2343 PH::CounterHandle, getConstantIntExpr(1))
2344 .callBuiltin("__builtin_hlsl_resource_getpointer",
2345 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
2346 PH::LastStmt)
2347 .dereference(PH::LastStmt)
2348 .assign(PH::LastStmt, PH::_0)
2349 .finalize();
2350}
2351
2353 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2354 ASTContext &AST = SemaRef.getASTContext();
2355 QualType ElemTy = getHandleElementType();
2356 QualType AddrSpaceElemTy =
2358 return BuiltinTypeMethodBuilder(*this, "Consume", ElemTy)
2359 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
2360 PH::CounterHandle, getConstantIntExpr(-1))
2361 .callBuiltin("__builtin_hlsl_resource_getpointer",
2362 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
2363 PH::LastStmt)
2364 .dereference(PH::LastStmt)
2365 .finalize();
2366}
2367
2370 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2371 ASTContext &AST = SemaRef.getASTContext();
2372 QualType UIntTy = AST.UnsignedIntTy;
2373
2374 QualType HandleTy = getResourceHandleField()->getType();
2375 auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr());
2376
2377 // Structured buffers except {RW}ByteAddressBuffer have overload
2378 // GetDimensions(out uint numStructs, out uint stride).
2379 if (AttrResTy->getAttrs().RawBuffer &&
2380 AttrResTy->getContainedType() != AST.Char8Ty) {
2381 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
2382 .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out)
2383 .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out)
2384 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
2385 PH::Handle, PH::_0)
2386 .callBuiltin("__builtin_hlsl_resource_getstride", QualType(),
2387 PH::Handle, PH::_1)
2388 .finalize();
2389 }
2390
2391 // Typed buffers and {RW}ByteAddressBuffer have overload
2392 // GetDimensions(out uint dim).
2393 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
2394 .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out)
2395 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
2396 PH::Handle, PH::_0)
2397 .finalize();
2398}
2399
2400} // namespace hlsl
2401} // 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:227
DeclarationNameTable DeclarationNames
Definition ASTContext.h:809
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:3178
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:227
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
DeclarationNameTable DeclarationNames
Definition ASTContext.h:809
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:805
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:2620
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
static CXXConversionDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, const AssociatedConstraint &TrailingRequiresClause={})
Definition DeclCXX.cpp:3275
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2132
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 getCXXConversionFunctionName(CanQualType Ty)
Returns the name of a C++ conversion function for the given Type.
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.
NameKind getNameKind() const
Determine what kind of name this is.
Represents an extended vector type where either the type or size is dependent.
Definition TypeBase.h:4156
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:3178
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3414
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:4695
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:2018
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2229
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:4584
ExtParameterInfo withABI(ParameterABI kind) const
Definition TypeBase.h:4598
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:2952
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType withConst() const
Definition TypeBase.h:1170
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1167
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:8436
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:3836
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:8407
The base class of the type hierarchy.
Definition TypeBase.h:1871
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:9333
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isVectorType() const
Definition TypeBase.h:8812
bool isRecordType() const
Definition TypeBase.h:8800
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:924
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2130
Represents a GCC generic vector type.
Definition TypeBase.h:4230
BuiltinTypeDeclBuilder & addStoreFunction(DeclarationName &Name, bool IsConst, QualType ValueType)
BuiltinTypeDeclBuilder & addDefaultHandleConstructor(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeDeclBuilder(Sema &SemaRef, CXXRecordDecl *R)
BuiltinTypeDeclBuilder & addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef< Attr * > Attrs, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addHandleAccessFunction(DeclarationName &Name, bool IsConstReturn, bool IsRef, QualType IndexTy, QualType ElemTy=QualType())
BuiltinTypeDeclBuilder & addCopyAssignmentOperator(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeDeclBuilder & addArraySubscriptOperators(ResourceDimension Dim=ResourceDimension::Unknown)
BuiltinTypeDeclBuilder & addSampleGradMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addGetDimensionsMethodForBuffer()
BuiltinTypeDeclBuilder & addGatherCmpMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addConstantBufferConversionToType()
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 & addLoadWithStatusFunction(DeclarationName &Name, QualType ReturnTy=QualType())
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 & addSimpleTemplateParams(ArrayRef< StringRef > Names, ConceptDecl *CD=nullptr)
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:1763
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)