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 = new (AST) InitListExpr(
658 AST, SourceLocation(), Elts, SourceLocation(), /*isExplicit=*/false);
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,
1042 /*IsArray=*/false, ElementTy, Access);
1043 if (HasCounter)
1044 addCounterHandleMember(RC, IsROV, RawBuffer, ElementTy, Access);
1045 return *this;
1046}
1047
1049BuiltinTypeDeclBuilder::addTextureHandle(ResourceClass RC, bool IsROV,
1050 bool IsArray, ResourceDimension RD,
1051 AccessSpecifier Access) {
1052 addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, IsArray,
1053 getHandleElementType(), Access);
1054 return *this;
1055}
1056
1058 addHandleMember(ResourceClass::Sampler, ResourceDimension::Unknown,
1059 /*IsROV=*/false, /*RawBuffer=*/false, /*IsArray=*/false,
1060 getHandleElementType());
1061 return *this;
1062}
1063
1066 assert(!Record->isCompleteDefinition() && "record is already complete");
1067 ASTContext &AST = SemaRef.getASTContext();
1068 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1069
1070 QualType ElemTy = getHandleElementType();
1071 QualType AddrSpaceElemTy = AST.getCanonicalType(
1073 QualType ReturnTy =
1074 AST.getCanonicalType(AST.getLValueReferenceType(AddrSpaceElemTy));
1075
1077 AST.getCanonicalType(ReturnTy));
1078
1079 return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, /*IsConst=*/true)
1080 .callBuiltin("__builtin_hlsl_resource_getpointer",
1081 AST.getPointerType(AddrSpaceElemTy), PH::Handle)
1082 .dereference(PH::LastStmt)
1083 .finalize();
1084}
1085
1087BuiltinTypeDeclBuilder::addFriend(CXXRecordDecl *Friend) {
1088 assert(!Record->isCompleteDefinition() && "record is already complete");
1089 ASTContext &AST = SemaRef.getASTContext();
1090 QualType FriendTy = AST.getCanonicalTagType(Friend);
1091 TypeSourceInfo *TSI = AST.getTrivialTypeSourceInfo(FriendTy);
1092 FriendDecl *FD =
1094 FD->setAccess(AS_public);
1095 Record->addDecl(FD);
1096 return *this;
1097}
1098
1099CXXRecordDecl *BuiltinTypeDeclBuilder::addPrivateNestedRecord(StringRef Name) {
1100 assert(!Record->isCompleteDefinition() && "record is already complete");
1101 ASTContext &AST = SemaRef.getASTContext();
1102 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
1103 CXXRecordDecl *NestedRecord =
1104 CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, Record,
1105 SourceLocation(), SourceLocation(), &II);
1106 NestedRecord->setImplicit(true);
1108 NestedRecord->setLexicalDeclContext(Record);
1109 Record->addDecl(NestedRecord);
1110 return NestedRecord;
1111}
1112
1113BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
1114 ResourceClass RC, ResourceDimension RD, bool IsROV, bool RawBuffer,
1115 bool IsArray, QualType ElementTy, AccessSpecifier Access) {
1116 return addResourceMember("__handle", RC, RD, IsROV, RawBuffer,
1117 /*IsCounter=*/false, IsArray, ElementTy, Access);
1118}
1119
1120BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
1121 ResourceClass RC, bool IsROV, bool RawBuffer, QualType ElementTy,
1122 AccessSpecifier Access) {
1123 return addResourceMember("__counter_handle", RC, ResourceDimension::Unknown,
1124 IsROV, RawBuffer, /*IsCounter=*/true,
1125 /*IsArray=*/false, ElementTy, Access);
1126}
1127
1128BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember(
1129 StringRef MemberName, ResourceClass RC, ResourceDimension RD, bool IsROV,
1130 bool RawBuffer, bool IsCounter, bool IsArray, QualType ElementTy,
1131 AccessSpecifier Access) {
1132 assert(!Record->isCompleteDefinition() && "record is already complete");
1133
1134 ASTContext &Ctx = SemaRef.getASTContext();
1135
1136 assert(!ElementTy.isNull() &&
1137 "The caller should always pass in the type for the handle.");
1138 TypeSourceInfo *ElementTypeInfo =
1139 Ctx.getTrivialTypeSourceInfo(ElementTy, SourceLocation());
1140
1141 // add handle member with resource type attributes
1142 QualType AttributedResTy = QualType();
1143 SmallVector<const Attr *> Attrs = {
1144 HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
1145 IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
1146 RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
1147 RD != ResourceDimension::Unknown
1148 ? HLSLResourceDimensionAttr::CreateImplicit(Ctx, RD)
1149 : nullptr,
1150 ElementTypeInfo && RC != ResourceClass::Sampler
1151 ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
1152 : nullptr};
1153 if (IsCounter)
1154 Attrs.push_back(HLSLIsCounterAttr::CreateImplicit(Ctx));
1155 if (IsArray)
1156 Attrs.push_back(HLSLIsArrayAttr::CreateImplicit(Ctx));
1157
1158 if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
1159 AttributedResTy))
1160 addMemberVariable(MemberName, AttributedResTy, {}, Access);
1161 return *this;
1162}
1163
1164// Adds default constructor to the resource class:
1165// Resource::Resource()
1168 assert(!Record->isCompleteDefinition() && "record is already complete");
1169
1170 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1171 QualType HandleType = getResourceHandleField()->getType();
1172 return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
1173 false, true)
1174 .callBuiltin("__builtin_hlsl_resource_uninitializedhandle", HandleType,
1175 PH::Handle)
1176 .assign(PH::Handle, PH::LastStmt)
1177 .finalize(Access);
1178}
1179
1182 if (HasCounter) {
1183 addCreateFromBindingWithImplicitCounter();
1184 addCreateFromImplicitBindingWithImplicitCounter();
1185 } else {
1186 addCreateFromBinding();
1187 addCreateFromImplicitBinding();
1188 }
1189 return *this;
1190}
1191
1192// Adds static method that initializes resource from binding:
1193//
1194// static Resource<T> __createFromBinding(unsigned registerNo,
1195// unsigned spaceNo, int range,
1196// unsigned index, const char *name) {
1197// Resource<T> tmp;
1198// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1199// tmp.__handle, registerNo, spaceNo,
1200// range, index, name);
1201// return tmp;
1202// }
1203BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
1204 assert(!Record->isCompleteDefinition() && "record is already complete");
1205
1206 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1207 ASTContext &AST = SemaRef.getASTContext();
1208 QualType HandleType = getResourceHandleField()->getType();
1209 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1210 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1211
1212 return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
1213 false, false, SC_Static)
1214 .addParam("registerNo", AST.UnsignedIntTy)
1215 .addParam("spaceNo", AST.UnsignedIntTy)
1216 .addParam("range", AST.IntTy)
1217 .addParam("index", AST.UnsignedIntTy)
1218 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1219 .declareLocalVar(TmpVar)
1220 .accessHandleFieldOnResource(TmpVar)
1221 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1222 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1223 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1224 .returnValue(TmpVar)
1225 .finalize();
1226}
1227
1228// Adds static method that initializes resource from binding:
1229//
1230// static Resource<T> __createFromImplicitBinding(unsigned orderId,
1231// unsigned spaceNo, int range,
1232// unsigned index,
1233// const char *name) {
1234// Resource<T> tmp;
1235// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1236// tmp.__handle, spaceNo,
1237// range, index, orderId, name);
1238// return tmp;
1239// }
1240BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
1241 assert(!Record->isCompleteDefinition() && "record is already complete");
1242
1243 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1244 ASTContext &AST = SemaRef.getASTContext();
1245 QualType HandleType = getResourceHandleField()->getType();
1246 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1247 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1248
1249 return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
1250 RecordType, false, false, SC_Static)
1251 .addParam("orderId", AST.UnsignedIntTy)
1252 .addParam("spaceNo", AST.UnsignedIntTy)
1253 .addParam("range", AST.IntTy)
1254 .addParam("index", AST.UnsignedIntTy)
1255 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1256 .declareLocalVar(TmpVar)
1257 .accessHandleFieldOnResource(TmpVar)
1258 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1259 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1260 PH::_4)
1261 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1262 .returnValue(TmpVar)
1263 .finalize();
1264}
1265
1266// Adds static method that initializes resource from binding:
1267//
1268// static Resource<T>
1269// __createFromBindingWithImplicitCounter(unsigned registerNo,
1270// unsigned spaceNo, int range,
1271// unsigned index, const char *name,
1272// unsigned counterOrderId) {
1273// Resource<T> tmp;
1274// tmp.__handle = __builtin_hlsl_resource_handlefrombinding(
1275// tmp.__handle, registerNo, spaceNo, range, index, name);
1276// tmp.__counter_handle =
1277// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1278// tmp.__handle, counterOrderId, spaceNo);
1279// return tmp;
1280// }
1282BuiltinTypeDeclBuilder::addCreateFromBindingWithImplicitCounter() {
1283 assert(!Record->isCompleteDefinition() && "record is already complete");
1284
1285 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1286 ASTContext &AST = SemaRef.getASTContext();
1287 QualType HandleType = getResourceHandleField()->getType();
1288 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1289 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1290 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1291
1292 return BuiltinTypeMethodBuilder(*this,
1293 "__createFromBindingWithImplicitCounter",
1294 RecordType, false, false, SC_Static)
1295 .addParam("registerNo", AST.UnsignedIntTy)
1296 .addParam("spaceNo", AST.UnsignedIntTy)
1297 .addParam("range", AST.IntTy)
1298 .addParam("index", AST.UnsignedIntTy)
1299 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1300 .addParam("counterOrderId", AST.UnsignedIntTy)
1301 .declareLocalVar(TmpVar)
1302 .accessHandleFieldOnResource(TmpVar)
1303 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
1304 PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
1305 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1306 .accessHandleFieldOnResource(TmpVar)
1307 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1308 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1309 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1310 .returnValue(TmpVar)
1311 .finalize();
1312}
1313
1314// Adds static method that initializes resource from binding:
1315//
1316// static Resource<T>
1317// __createFromImplicitBindingWithImplicitCounter(unsigned orderId,
1318// unsigned spaceNo, int range,
1319// unsigned index,
1320// const char *name,
1321// unsigned counterOrderId) {
1322// Resource<T> tmp;
1323// tmp.__handle = __builtin_hlsl_resource_handlefromimplicitbinding(
1324// tmp.__handle, orderId, spaceNo, range, index, name);
1325// tmp.__counter_handle =
1326// __builtin_hlsl_resource_counterhandlefromimplicitbinding(
1327// tmp.__handle, counterOrderId, spaceNo);
1328// return tmp;
1329// }
1331BuiltinTypeDeclBuilder::addCreateFromImplicitBindingWithImplicitCounter() {
1332 assert(!Record->isCompleteDefinition() && "record is already complete");
1333
1334 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1335 ASTContext &AST = SemaRef.getASTContext();
1336 QualType HandleType = getResourceHandleField()->getType();
1337 QualType CounterHandleType = getResourceCounterHandleField()->getType();
1338 QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
1339 BuiltinTypeMethodBuilder::LocalVar TmpVar("tmp", RecordType);
1340
1342 *this, "__createFromImplicitBindingWithImplicitCounter",
1343 RecordType, false, false, SC_Static)
1344 .addParam("orderId", AST.UnsignedIntTy)
1345 .addParam("spaceNo", AST.UnsignedIntTy)
1346 .addParam("range", AST.IntTy)
1347 .addParam("index", AST.UnsignedIntTy)
1348 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
1349 .addParam("counterOrderId", AST.UnsignedIntTy)
1350 .declareLocalVar(TmpVar)
1351 .accessHandleFieldOnResource(TmpVar)
1352 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
1353 HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
1354 PH::_4)
1355 .setHandleFieldOnResource(TmpVar, PH::LastStmt)
1356 .accessHandleFieldOnResource(TmpVar)
1357 .callBuiltin("__builtin_hlsl_resource_counterhandlefromimplicitbinding",
1358 CounterHandleType, PH::LastStmt, PH::_5, PH::_1)
1359 .setCounterHandleFieldOnResource(TmpVar, PH::LastStmt)
1360 .returnValue(TmpVar)
1361 .finalize();
1362}
1363
1366 assert(!Record->isCompleteDefinition() && "record is already complete");
1367
1368 ASTContext &AST = SemaRef.getASTContext();
1369 QualType RecordType = AST.getCanonicalTagType(Record);
1370 QualType ConstRecordType = RecordType.withConst();
1371 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1372
1373 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1374
1375 BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy,
1376 /*IsConst=*/false, /*IsCtor=*/true);
1377 MMB.addParam("other", ConstRecordRefType);
1378
1379 for (auto *Field : Record->fields()) {
1380 MMB.accessFieldOnResource(PH::_0, Field)
1381 .setFieldOnResource(PH::This, PH::LastStmt, Field);
1382 }
1383
1384 return MMB.finalize(Access);
1385}
1386
1389 assert(!Record->isCompleteDefinition() && "record is already complete");
1390
1391 ASTContext &AST = SemaRef.getASTContext();
1392 QualType RecordType = AST.getCanonicalTagType(Record);
1393 QualType ConstRecordType = RecordType.withConst();
1394 QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
1395 QualType RecordRefType = AST.getLValueReferenceType(RecordType);
1396
1397 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1399 BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType);
1400 MMB.addParam("other", ConstRecordRefType);
1401
1402 for (auto *Field : Record->fields()) {
1403 MMB.accessFieldOnResource(PH::_0, Field)
1404 .setFieldOnResource(PH::This, PH::LastStmt, Field);
1405 }
1406
1407 return MMB.returnThis().finalize(Access);
1408}
1409
1412 bool IsArray) {
1413 assert(!Record->isCompleteDefinition() && "record is already complete");
1414 ASTContext &AST = Record->getASTContext();
1415
1416 uint32_t VecSize = 1;
1417 if (Dim != ResourceDimension::Unknown)
1418 VecSize = getResourceDimensions(Dim) + (IsArray ? 1 : 0);
1419
1420 QualType IndexTy = VecSize > 1
1421 ? AST.getExtVectorType(AST.UnsignedIntTy, VecSize)
1422 : AST.UnsignedIntTy;
1423
1424 DeclarationName Subscript =
1425 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1426
1427 addHandleAccessFunction(Subscript,
1428 /*IsConstReturn=*/getResourceAttrs().ResourceClass !=
1429 llvm::dxil::ResourceClass::UAV,
1430 /*IsRef=*/true, IndexTy);
1431
1432 return *this;
1433}
1434
1436 assert(!Record->isCompleteDefinition() && "record is already complete");
1437
1438 ASTContext &AST = Record->getASTContext();
1439 IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
1440 DeclarationName Load(&II);
1441
1443 /*IsConstReturn=*/false, /*IsRef=*/false,
1444 AST.UnsignedIntTy);
1446
1447 return *this;
1448}
1449
1450CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsSliceType(ResourceDimension Dim,
1451 QualType ReturnType) {
1452 ASTContext &AST = Record->getASTContext();
1453 uint32_t VecSize =
1454 getResourceDimensions(Dim) + (getResourceAttrs().IsArray ? 1 : 0);
1455 QualType IntTy = AST.IntTy;
1456 QualType IndexTy = VecSize > 1 ? AST.getExtVectorType(IntTy, VecSize) : IntTy;
1457 QualType CoordLevelTy = AST.getExtVectorType(IntTy, VecSize + 1);
1458 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1459
1460 // Define the mips_slice_type which is returned by mips_type::operator[].
1461 // It holds the resource handle and the mip level. It has an operator[]
1462 // that takes the coordinate and performs the actual resource load.
1463 CXXRecordDecl *MipsSliceRecord = addPrivateNestedRecord("mips_slice_type");
1464 BuiltinTypeDeclBuilder MipsSliceBuilder(SemaRef, MipsSliceRecord);
1465 MipsSliceBuilder.addFriend(Record)
1466 .addHandleMember(getResourceAttrs().ResourceClass, Dim,
1467 getResourceAttrs().IsROV, /*RawBuffer=*/false,
1468 getResourceAttrs().IsArray, ReturnType,
1470 .addMemberVariable("__level", IntTy, {}, AccessSpecifier::AS_public)
1474
1475 FieldDecl *LevelField = MipsSliceBuilder.Fields["__level"];
1476 assert(LevelField && "Could not find the level field.");
1477
1478 DeclarationName SubscriptName =
1479 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1480
1481 // operator[](intN coord) on mips_slice_type
1482 BuiltinTypeMethodBuilder(MipsSliceBuilder, SubscriptName, ReturnType,
1483 /*IsConst=*/true)
1484 .addParam("Coord", IndexTy)
1485 .accessFieldOnResource(PH::This, LevelField)
1486 .concat(PH::_0, PH::LastStmt, CoordLevelTy)
1487 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1488 PH::LastStmt)
1489 .finalize();
1490
1491 MipsSliceBuilder.completeDefinition();
1492 return MipsSliceRecord;
1493}
1494
1495CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsType(ResourceDimension Dim,
1496 QualType ReturnType) {
1497 ASTContext &AST = Record->getASTContext();
1498 QualType IntTy = AST.IntTy;
1499 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1500
1501 // First, define the mips_slice_type that will be returned by our operator[].
1502 CXXRecordDecl *MipsSliceRecord = addMipsSliceType(Dim, ReturnType);
1503
1504 // Define the mips_type, which provides the syntax `Resource.mips[level]`.
1505 // It only holds the handle, and its operator[] returns a mips_slice_type
1506 // initialized with the handle and the requested mip level.
1507 CXXRecordDecl *MipsRecord = addPrivateNestedRecord("mips_type");
1508 BuiltinTypeDeclBuilder MipsBuilder(SemaRef, MipsRecord);
1509 MipsBuilder.addFriend(Record)
1510 .addHandleMember(getResourceAttrs().ResourceClass, Dim,
1511 getResourceAttrs().IsROV, /*RawBuffer=*/false,
1512 getResourceAttrs().IsArray, ReturnType,
1514 .addDefaultHandleConstructor(AccessSpecifier::AS_protected)
1515 .addCopyConstructor(AccessSpecifier::AS_protected)
1516 .addCopyAssignmentOperator(AccessSpecifier::AS_protected);
1517
1518 QualType MipsSliceTy = AST.getCanonicalTagType(MipsSliceRecord);
1519
1520 DeclarationName SubscriptName =
1521 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
1522
1523 // Locate the fields in the slice type so we can initialize them.
1524 auto FieldIt = MipsSliceRecord->field_begin();
1525 FieldDecl *MipsSliceHandleField = *FieldIt;
1526 FieldDecl *LevelField = *++FieldIt;
1527 assert(MipsSliceHandleField->getName() == "__handle" &&
1528 LevelField->getName() == "__level" &&
1529 "Could not find fields on mips_slice_type");
1530
1531 // operator[](int level) on mips_type
1532 BuiltinTypeMethodBuilder::LocalVar MipsSliceVar("slice", MipsSliceTy);
1533 BuiltinTypeMethodBuilder(MipsBuilder, SubscriptName, MipsSliceTy,
1534 /*IsConst=*/true)
1535 .addParam("Level", IntTy)
1536 .declareLocalVar(MipsSliceVar)
1537 .accessHandleFieldOnResource(PH::This)
1538 .setFieldOnResource(MipsSliceVar, PH::LastStmt, MipsSliceHandleField)
1539 .setFieldOnResource(MipsSliceVar, PH::_0, LevelField)
1540 .returnValue(MipsSliceVar)
1541 .finalize();
1542
1543 MipsBuilder.completeDefinition();
1544 return MipsRecord;
1545}
1546
1549 assert(!Record->isCompleteDefinition() && "record is already complete");
1550 ASTContext &AST = Record->getASTContext();
1551 QualType ReturnType = getHandleElementType();
1552
1553 CXXRecordDecl *MipsRecord = addMipsType(Dim, ReturnType);
1554
1555 // Add the mips field to the texture
1556 QualType MipsTy = AST.getCanonicalTagType(MipsRecord);
1557 addMemberVariable("mips", MipsTy, {}, AccessSpecifier::AS_public);
1558
1559 return *this;
1560}
1561
1564 bool IsArray) {
1565 assert(!Record->isCompleteDefinition() && "record is already complete");
1566 ASTContext &AST = Record->getASTContext();
1567 uint32_t OffsetSize = getResourceDimensions(Dim);
1568 uint32_t CoordSize = OffsetSize + (IsArray ? 2 : 1);
1569 QualType IntTy = AST.IntTy;
1570 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
1571 QualType LocationTy = AST.getExtVectorType(IntTy, CoordSize);
1572 QualType ReturnType = getHandleElementType();
1573
1574 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1575
1576 // T Load(int3 location)
1577 BuiltinTypeMethodBuilder(*this, "Load", ReturnType)
1578 .addParam("Location", LocationTy)
1579 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1580 PH::_0)
1581 .finalize();
1582
1583 // T Load(int3 location, int2 offset)
1584 return BuiltinTypeMethodBuilder(*this, "Load", ReturnType)
1585 .addParam("Location", LocationTy)
1586 .addParam("Offset", OffsetTy)
1587 .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle,
1588 PH::_0, PH::_1)
1589 .finalize();
1590}
1591
1594 assert(!Record->isCompleteDefinition() && "record is already complete");
1595
1596 ASTContext &AST = SemaRef.getASTContext();
1597
1598 auto AddLoads = [&](StringRef MethodName, QualType ReturnType) {
1599 IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
1600 DeclarationName Load(&II);
1601
1603 /*IsConstReturn=*/false, /*IsRef=*/false,
1604 AST.UnsignedIntTy, ReturnType);
1605 addLoadWithStatusFunction(Load, ReturnType);
1606 };
1607
1608 AddLoads("Load", AST.UnsignedIntTy);
1609 AddLoads("Load2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
1610 AddLoads("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
1611 AddLoads("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
1612 AddLoads("Load", AST.DependentTy); // Templated version
1613 return *this;
1614}
1615
1618 assert(!Record->isCompleteDefinition() && "record is already complete");
1619
1620 ASTContext &AST = SemaRef.getASTContext();
1621
1622 auto AddStore = [&](StringRef MethodName, QualType ValueType) {
1623 IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
1624 DeclarationName Store(&II);
1625
1626 addStoreFunction(Store, /*IsConst=*/false, ValueType);
1627 };
1628
1629 AddStore("Store", AST.UnsignedIntTy);
1630 AddStore("Store2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
1631 AddStore("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
1632 AddStore("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
1633 AddStore("Store", AST.DependentTy); // Templated version
1634
1635 return *this;
1636}
1637
1639BuiltinTypeDeclBuilder::addSampleMethods(ResourceDimension Dim, bool IsArray) {
1640 assert(!Record->isCompleteDefinition() && "record is already complete");
1641 ASTContext &AST = Record->getASTContext();
1642 QualType ReturnType = getHandleElementType();
1643 QualType SamplerStateType =
1644 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1645 uint32_t OffsetSize = getResourceDimensions(Dim);
1646 uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
1647 QualType FloatTy = AST.FloatTy;
1648 QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
1649 QualType IntTy = AST.IntTy;
1650 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
1651 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1652
1653 // T Sample(SamplerState s, float2 location)
1654 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1655 .addParam("Sampler", SamplerStateType)
1656 .addParam("Location", CoordTy)
1657 .accessHandleFieldOnResource(PH::_0)
1658 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1659 PH::LastStmt, PH::_1)
1660 .returnValue(PH::LastStmt)
1661 .finalize();
1662
1663 // T Sample(SamplerState s, float2 location, int2 offset)
1664 BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1665 .addParam("Sampler", SamplerStateType)
1666 .addParam("Location", CoordTy)
1667 .addParam("Offset", OffsetTy)
1668 .accessHandleFieldOnResource(PH::_0)
1669 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1670 PH::LastStmt, PH::_1, PH::_2)
1671 .returnValue(PH::LastStmt)
1672 .finalize();
1673
1674 // T Sample(SamplerState s, float2 location, int2 offset, float clamp)
1675 return BuiltinTypeMethodBuilder(*this, "Sample", ReturnType)
1676 .addParam("Sampler", SamplerStateType)
1677 .addParam("Location", CoordTy)
1678 .addParam("Offset", OffsetTy)
1679 .addParam("Clamp", FloatTy)
1680 .accessHandleFieldOnResource(PH::_0)
1681 .callBuiltin("__builtin_hlsl_resource_sample", ReturnType, PH::Handle,
1682 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1683 .returnValue(PH::LastStmt)
1684 .finalize();
1685}
1686
1689 bool IsArray) {
1690 assert(!Record->isCompleteDefinition() && "record is already complete");
1691 ASTContext &AST = Record->getASTContext();
1692 QualType ReturnType = getHandleElementType();
1693 QualType SamplerStateType =
1694 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1695 uint32_t OffsetSize = getResourceDimensions(Dim);
1696 uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
1697 QualType FloatTy = AST.FloatTy;
1698 QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
1699 QualType IntTy = AST.IntTy;
1700 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
1701 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1702
1703 // T SampleBias(SamplerState s, float2 location, float bias)
1704 BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1705 .addParam("Sampler", SamplerStateType)
1706 .addParam("Location", CoordTy)
1707 .addParam("Bias", FloatTy)
1708 .accessHandleFieldOnResource(PH::_0)
1709 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1710 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1711 .returnValue(PH::LastStmt)
1712 .finalize();
1713
1714 // T SampleBias(SamplerState s, float2 location, float bias, int2 offset)
1715 BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1716 .addParam("Sampler", SamplerStateType)
1717 .addParam("Location", CoordTy)
1718 .addParam("Bias", FloatTy)
1719 .addParam("Offset", OffsetTy)
1720 .accessHandleFieldOnResource(PH::_0)
1721 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1722 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1723 .returnValue(PH::LastStmt)
1724 .finalize();
1725
1726 // T SampleBias(SamplerState s, float2 location, float bias, int2 offset,
1727 // float clamp)
1728 return BuiltinTypeMethodBuilder(*this, "SampleBias", ReturnType)
1729 .addParam("Sampler", SamplerStateType)
1730 .addParam("Location", CoordTy)
1731 .addParam("Bias", FloatTy)
1732 .addParam("Offset", OffsetTy)
1733 .addParam("Clamp", FloatTy)
1734 .accessHandleFieldOnResource(PH::_0)
1735 .callBuiltin("__builtin_hlsl_resource_sample_bias", ReturnType,
1736 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1737 .returnValue(PH::LastStmt)
1738 .finalize();
1739}
1740
1743 bool IsArray) {
1744 assert(!Record->isCompleteDefinition() && "record is already complete");
1745 ASTContext &AST = Record->getASTContext();
1746 QualType ReturnType = getHandleElementType();
1747 QualType SamplerStateType =
1748 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1749 uint32_t OffsetSize = getResourceDimensions(Dim);
1750 uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
1751 QualType FloatTy = AST.FloatTy;
1752 QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
1753 QualType OffsetFloatTy = AST.getExtVectorType(FloatTy, OffsetSize);
1754 QualType IntTy = AST.IntTy;
1755 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
1756 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1757
1758 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy)
1759 BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1760 .addParam("Sampler", SamplerStateType)
1761 .addParam("Location", CoordTy)
1762 .addParam("DDX", OffsetFloatTy)
1763 .addParam("DDY", OffsetFloatTy)
1764 .accessHandleFieldOnResource(PH::_0)
1765 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1766 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1767 .returnValue(PH::LastStmt)
1768 .finalize();
1769
1770 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy,
1771 // int2 offset)
1772 BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1773 .addParam("Sampler", SamplerStateType)
1774 .addParam("Location", CoordTy)
1775 .addParam("DDX", OffsetFloatTy)
1776 .addParam("DDY", OffsetFloatTy)
1777 .addParam("Offset", OffsetTy)
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 .returnValue(PH::LastStmt)
1782 .finalize();
1783
1784 // T SampleGrad(SamplerState s, float2 location, float2 ddx, float2 ddy,
1785 // int2 offset, float clamp)
1786 return BuiltinTypeMethodBuilder(*this, "SampleGrad", ReturnType)
1787 .addParam("Sampler", SamplerStateType)
1788 .addParam("Location", CoordTy)
1789 .addParam("DDX", OffsetFloatTy)
1790 .addParam("DDY", OffsetFloatTy)
1791 .addParam("Offset", OffsetTy)
1792 .addParam("Clamp", FloatTy)
1793 .accessHandleFieldOnResource(PH::_0)
1794 .callBuiltin("__builtin_hlsl_resource_sample_grad", ReturnType,
1795 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4,
1796 PH::_5)
1797 .returnValue(PH::LastStmt)
1798 .finalize();
1799}
1800
1803 bool IsArray) {
1804 assert(!Record->isCompleteDefinition() && "record is already complete");
1805 ASTContext &AST = Record->getASTContext();
1806 QualType ReturnType = getHandleElementType();
1807 QualType SamplerStateType =
1808 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1809 uint32_t OffsetSize = getResourceDimensions(Dim);
1810 uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
1811 QualType FloatTy = AST.FloatTy;
1812 QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
1813 QualType IntTy = AST.IntTy;
1814 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
1815 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1816
1817 // T SampleLevel(SamplerState s, float2 location, float lod)
1818 BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
1819 .addParam("Sampler", SamplerStateType)
1820 .addParam("Location", CoordTy)
1821 .addParam("LOD", FloatTy)
1822 .accessHandleFieldOnResource(PH::_0)
1823 .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
1824 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1825 .returnValue(PH::LastStmt)
1826 .finalize();
1827
1828 // T SampleLevel(SamplerState s, float2 location, float lod, int2 offset)
1829 return BuiltinTypeMethodBuilder(*this, "SampleLevel", ReturnType)
1830 .addParam("Sampler", SamplerStateType)
1831 .addParam("Location", CoordTy)
1832 .addParam("LOD", FloatTy)
1833 .addParam("Offset", OffsetTy)
1834 .accessHandleFieldOnResource(PH::_0)
1835 .callBuiltin("__builtin_hlsl_resource_sample_level", ReturnType,
1836 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1837 .returnValue(PH::LastStmt)
1838 .finalize();
1839}
1840
1843 bool IsArray) {
1844 assert(!Record->isCompleteDefinition() && "record is already complete");
1845 ASTContext &AST = Record->getASTContext();
1846 QualType ReturnType = AST.FloatTy;
1847 QualType SamplerComparisonStateType = lookupBuiltinType(
1848 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1849 uint32_t OffsetSize = getResourceDimensions(Dim);
1850 uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
1851 QualType FloatTy = AST.FloatTy;
1852 QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
1853 QualType IntTy = AST.IntTy;
1854 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
1855 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1856
1857 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value)
1858 BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1859 .addParam("Sampler", SamplerComparisonStateType)
1860 .addParam("Location", CoordTy)
1861 .addParam("CompareValue", FloatTy)
1862 .accessHandleFieldOnResource(PH::_0)
1863 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1864 PH::LastStmt, PH::_1, PH::_2)
1865 .returnValue(PH::LastStmt)
1866 .finalize();
1867
1868 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value,
1869 // int2 offset)
1870 BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1871 .addParam("Sampler", SamplerComparisonStateType)
1872 .addParam("Location", CoordTy)
1873 .addParam("CompareValue", FloatTy)
1874 .addParam("Offset", OffsetTy)
1875 .accessHandleFieldOnResource(PH::_0)
1876 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1877 PH::LastStmt, PH::_1, PH::_2, PH::_3)
1878 .returnValue(PH::LastStmt)
1879 .finalize();
1880
1881 // T SampleCmp(SamplerComparisonState s, float2 location, float compare_value,
1882 // int2 offset, float clamp)
1883 return BuiltinTypeMethodBuilder(*this, "SampleCmp", ReturnType)
1884 .addParam("Sampler", SamplerComparisonStateType)
1885 .addParam("Location", CoordTy)
1886 .addParam("CompareValue", FloatTy)
1887 .addParam("Offset", OffsetTy)
1888 .addParam("Clamp", FloatTy)
1889 .accessHandleFieldOnResource(PH::_0)
1890 .callBuiltin("__builtin_hlsl_resource_sample_cmp", ReturnType, PH::Handle,
1891 PH::LastStmt, PH::_1, PH::_2, PH::_3, PH::_4)
1892 .returnValue(PH::LastStmt)
1893 .finalize();
1894}
1895
1898 bool IsArray) {
1899 assert(!Record->isCompleteDefinition() && "record is already complete");
1900 ASTContext &AST = Record->getASTContext();
1901 QualType ReturnType = AST.FloatTy;
1902 QualType SamplerComparisonStateType = lookupBuiltinType(
1903 SemaRef, "SamplerComparisonState", Record->getDeclContext());
1904 uint32_t OffsetSize = getResourceDimensions(Dim);
1905 uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
1906 QualType FloatTy = AST.FloatTy;
1907 QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
1908 QualType IntTy = AST.IntTy;
1909 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
1910 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1911
1912 // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
1913 // compare_value)
1914 BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
1915 .addParam("Sampler", SamplerComparisonStateType)
1916 .addParam("Location", CoordTy)
1917 .addParam("CompareValue", FloatTy)
1918 .accessHandleFieldOnResource(PH::_0)
1919 .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
1920 PH::Handle, PH::LastStmt, PH::_1, PH::_2)
1921 .returnValue(PH::LastStmt)
1922 .finalize();
1923
1924 // T SampleCmpLevelZero(SamplerComparisonState s, float2 location, float
1925 // compare_value, int2 offset)
1926 return BuiltinTypeMethodBuilder(*this, "SampleCmpLevelZero", ReturnType)
1927 .addParam("Sampler", SamplerComparisonStateType)
1928 .addParam("Location", CoordTy)
1929 .addParam("CompareValue", FloatTy)
1930 .addParam("Offset", OffsetTy)
1931 .accessHandleFieldOnResource(PH::_0)
1932 .callBuiltin("__builtin_hlsl_resource_sample_cmp_level_zero", ReturnType,
1933 PH::Handle, PH::LastStmt, PH::_1, PH::_2, PH::_3)
1934 .returnValue(PH::LastStmt)
1935 .finalize();
1936}
1937
1940 assert(!Record->isCompleteDefinition() && "record is already complete");
1941 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1942 ASTContext &AST = SemaRef.getASTContext();
1943 QualType UIntTy = AST.UnsignedIntTy;
1944
1945 assert(Dim != ResourceDimension::Unknown);
1946
1947 QualType FloatTy = AST.FloatTy;
1948 // Add overloads for uint and float.
1949 QualType Params[] = {UIntTy, FloatTy};
1950
1951 for (QualType OutTy : Params) {
1952 if (Dim == ResourceDimension::Dim2D) {
1953 StringRef XYName = "__builtin_hlsl_resource_getdimensions_xy";
1954 StringRef LevelsXYName =
1955 "__builtin_hlsl_resource_getdimensions_levels_xy";
1956
1957 if (OutTy == FloatTy) {
1958 XYName = "__builtin_hlsl_resource_getdimensions_xy_float";
1959 LevelsXYName = "__builtin_hlsl_resource_getdimensions_levels_xy_float";
1960 }
1961
1962 // void GetDimensions(out [uint|float] width, out [uint|float] height)
1963 BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
1964 .addParam("width", OutTy, HLSLParamModifierAttr::Keyword_out)
1965 .addParam("height", OutTy, HLSLParamModifierAttr::Keyword_out)
1966 .callBuiltin(XYName, QualType(), PH::Handle, PH::_0, PH::_1)
1967 .finalize();
1968
1969 // void GetDimensions(uint mipLevel, out [uint|float] width, out
1970 // [uint|float] height, out [uint|float] numberOfLevels)
1971 BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
1972 .addParam("mipLevel", UIntTy)
1973 .addParam("width", OutTy, HLSLParamModifierAttr::Keyword_out)
1974 .addParam("height", OutTy, HLSLParamModifierAttr::Keyword_out)
1975 .addParam("numberOfLevels", OutTy, HLSLParamModifierAttr::Keyword_out)
1976 .callBuiltin(LevelsXYName, QualType(), PH::Handle, PH::_0, PH::_1,
1977 PH::_2, PH::_3)
1978 .finalize();
1979 }
1980 }
1981
1982 return *this;
1983}
1984
1987 assert(!Record->isCompleteDefinition() && "record is already complete");
1988 ASTContext &AST = Record->getASTContext();
1989 QualType ReturnType = AST.FloatTy;
1990 QualType SamplerStateType =
1991 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
1992 uint32_t VecSize = getResourceDimensions(Dim);
1993 QualType FloatTy = AST.FloatTy;
1994 QualType LocationTy = AST.getExtVectorType(FloatTy, VecSize);
1995 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1996
1997 // float CalculateLevelOfDetail(SamplerState s, float2 location)
1998 BuiltinTypeMethodBuilder(*this, "CalculateLevelOfDetail", ReturnType)
1999 .addParam("Sampler", SamplerStateType)
2000 .addParam("Location", LocationTy)
2001 .accessHandleFieldOnResource(PH::_0)
2002 .callBuiltin("__builtin_hlsl_resource_calculate_lod", ReturnType,
2003 PH::Handle, PH::LastStmt, PH::_1)
2004 .finalize();
2005
2006 // float CalculateLevelOfDetailUnclamped(SamplerState s, float2 location)
2007 return BuiltinTypeMethodBuilder(*this, "CalculateLevelOfDetailUnclamped",
2008 ReturnType)
2009 .addParam("Sampler", SamplerStateType)
2010 .addParam("Location", LocationTy)
2011 .accessHandleFieldOnResource(PH::_0)
2012 .callBuiltin("__builtin_hlsl_resource_calculate_lod_unclamped",
2013 ReturnType, PH::Handle, PH::LastStmt, PH::_1)
2014 .finalize();
2015}
2016
2017QualType BuiltinTypeDeclBuilder::getGatherReturnType() {
2018 ASTContext &AST = SemaRef.getASTContext();
2019 QualType T = getHandleElementType();
2020 if (T.isNull())
2021 return QualType();
2022
2023 if (const auto *VT = T->getAs<VectorType>())
2024 T = VT->getElementType();
2025 else if (const auto *DT = T->getAs<DependentSizedExtVectorType>())
2026 T = DT->getElementType();
2027
2028 return AST.getExtVectorType(T, 4);
2029}
2030
2032BuiltinTypeDeclBuilder::addGatherMethods(ResourceDimension Dim, bool IsArray) {
2033 assert(!Record->isCompleteDefinition() && "record is already complete");
2034 ASTContext &AST = Record->getASTContext();
2035 QualType ReturnType = getGatherReturnType();
2036
2037 QualType SamplerStateType =
2038 lookupBuiltinType(SemaRef, "SamplerState", Record->getDeclContext());
2039 uint32_t OffsetSize = getResourceDimensions(Dim);
2040 uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
2041 QualType LocationTy = AST.FloatTy;
2042 QualType CoordTy = AST.getExtVectorType(LocationTy, CoordSize);
2043 QualType IntTy = AST.IntTy;
2044 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
2045 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2046
2047 // Overloads for Gather, GatherRed, GatherGreen, GatherBlue, GatherAlpha
2048 struct GatherVariant {
2049 const char *Name;
2050 int Component;
2051 };
2052 GatherVariant Variants[] = {{"Gather", 0},
2053 {"GatherRed", 0},
2054 {"GatherGreen", 1},
2055 {"GatherBlue", 2},
2056 {"GatherAlpha", 3}};
2057
2058 for (const auto &V : Variants) {
2059 // ret GatherVariant(SamplerState s, float2 location)
2060 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2061 .addParam("Sampler", SamplerStateType)
2062 .addParam("Location", CoordTy)
2063 .accessHandleFieldOnResource(PH::_0)
2064 .callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
2065 PH::LastStmt, PH::_1,
2066 getConstantUnsignedIntExpr(V.Component))
2067 .finalize();
2068
2069 // ret GatherVariant(SamplerState s, float2 location, int2 offset)
2070 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2071 .addParam("Sampler", SamplerStateType)
2072 .addParam("Location", CoordTy)
2073 .addParam("Offset", OffsetTy)
2074 .accessHandleFieldOnResource(PH::_0)
2075 .callBuiltin("__builtin_hlsl_resource_gather", ReturnType, PH::Handle,
2076 PH::LastStmt, PH::_1,
2077 getConstantUnsignedIntExpr(V.Component), PH::_2)
2078 .finalize();
2079 }
2080
2081 return *this;
2082}
2083
2086 bool IsArray) {
2087 assert(!Record->isCompleteDefinition() && "record is already complete");
2088 ASTContext &AST = Record->getASTContext();
2089 QualType ReturnType = AST.getExtVectorType(AST.FloatTy, 4);
2090
2091 QualType SamplerComparisonStateType = lookupBuiltinType(
2092 SemaRef, "SamplerComparisonState", Record->getDeclContext());
2093 uint32_t OffsetSize = getResourceDimensions(Dim);
2094 uint32_t CoordSize = OffsetSize + (IsArray ? 1 : 0);
2095 QualType FloatTy = AST.FloatTy;
2096 QualType CoordTy = AST.getExtVectorType(FloatTy, CoordSize);
2097 QualType IntTy = AST.IntTy;
2098 QualType OffsetTy = AST.getExtVectorType(IntTy, OffsetSize);
2099 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2100
2101 // Overloads for GatherCmp, GatherCmpRed, GatherCmpGreen, GatherCmpBlue,
2102 // GatherCmpAlpha
2103 struct GatherVariant {
2104 const char *Name;
2105 int Component;
2106 };
2107 GatherVariant Variants[] = {{"GatherCmp", 0},
2108 {"GatherCmpRed", 0},
2109 {"GatherCmpGreen", 1},
2110 {"GatherCmpBlue", 2},
2111 {"GatherCmpAlpha", 3}};
2112
2113 for (const auto &V : Variants) {
2114 // ret GatherCmpVariant(SamplerComparisonState s, float2 location, float
2115 // compare_value)
2116 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2117 .addParam("Sampler", SamplerComparisonStateType)
2118 .addParam("Location", CoordTy)
2119 .addParam("CompareValue", FloatTy)
2120 .accessHandleFieldOnResource(PH::_0)
2121 .callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
2122 PH::Handle, PH::LastStmt, PH::_1, PH::_2,
2123 getConstantUnsignedIntExpr(V.Component))
2124 .finalize();
2125
2126 // ret GatherCmpVariant(SamplerComparisonState s, float2 location, float
2127 // compare_value, int2 offset)
2128 BuiltinTypeMethodBuilder(*this, V.Name, ReturnType)
2129 .addParam("Sampler", SamplerComparisonStateType)
2130 .addParam("Location", CoordTy)
2131 .addParam("CompareValue", FloatTy)
2132 .addParam("Offset", OffsetTy)
2133 .accessHandleFieldOnResource(PH::_0)
2134 .callBuiltin("__builtin_hlsl_resource_gather_cmp", ReturnType,
2135 PH::Handle, PH::LastStmt, PH::_1, PH::_2,
2136 getConstantUnsignedIntExpr(V.Component), PH::_3)
2137 .finalize();
2138 }
2139
2140 return *this;
2141}
2142
2143FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
2144 auto I = Fields.find("__handle");
2145 assert(I != Fields.end() &&
2146 I->second->getType()->isHLSLAttributedResourceType() &&
2147 "record does not have resource handle field");
2148 return I->second;
2149}
2150
2151FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField() const {
2152 auto I = Fields.find("__counter_handle");
2153 if (I == Fields.end() ||
2154 !I->second->getType()->isHLSLAttributedResourceType())
2155 return nullptr;
2156 return I->second;
2157}
2158
2159QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
2160 assert(Template && "record it not a template");
2161 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
2162 Template->getTemplateParameters()->getParam(0))) {
2163 return QualType(TTD->getTypeForDecl(), 0);
2164 }
2165 return QualType();
2166}
2167
2168QualType BuiltinTypeDeclBuilder::getHandleElementType() {
2169 if (Template)
2170 return getFirstTemplateTypeParam();
2171
2172 if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
2173 const auto &Args = Spec->getTemplateArgs();
2174 if (Args.size() > 0 && Args[0].getKind() == TemplateArgument::Type)
2175 return Args[0].getAsType();
2176 }
2177
2178 // TODO: Should we default to VoidTy? Using `i8` is arguably ambiguous.
2179 return SemaRef.getASTContext().Char8Ty;
2180}
2181
2182HLSLAttributedResourceType::Attributes
2183BuiltinTypeDeclBuilder::getResourceAttrs() const {
2184 QualType HandleType = getResourceHandleField()->getType();
2185 return cast<HLSLAttributedResourceType>(HandleType)->getAttrs();
2186}
2187
2189 assert(!Record->isCompleteDefinition() && "record is already complete");
2190 assert(Record->isBeingDefined() &&
2191 "Definition must be started before completing it.");
2192
2193 Record->completeDefinition();
2194 Record->setIsHLSLBuiltinRecord(true);
2195 return *this;
2196}
2197
2198Expr *BuiltinTypeDeclBuilder::getConstantIntExpr(int value) {
2199 ASTContext &AST = SemaRef.getASTContext();
2201 AST, llvm::APInt(AST.getTypeSize(AST.IntTy), value, true), AST.IntTy,
2202 SourceLocation());
2203}
2204
2205Expr *BuiltinTypeDeclBuilder::getConstantUnsignedIntExpr(unsigned value) {
2206 ASTContext &AST = SemaRef.getASTContext();
2208 AST, llvm::APInt(AST.getTypeSize(AST.UnsignedIntTy), value),
2210}
2211
2217
2220 ArrayRef<QualType> DefaultTypes,
2221 ConceptDecl *CD) {
2222 if (Record->isCompleteDefinition()) {
2223 assert(Template && "existing record it not a template");
2224 assert(Template->getTemplateParameters()->size() == Names.size() &&
2225 "template param count mismatch");
2226 return *this;
2227 }
2228
2229 assert((DefaultTypes.empty() || DefaultTypes.size() == Names.size()) &&
2230 "template default argument count mismatch");
2231
2233 for (unsigned i = 0; i < Names.size(); ++i) {
2234 QualType DefaultTy = DefaultTypes.empty() ? QualType() : DefaultTypes[i];
2235 Builder.addTypeParameter(Names[i], DefaultTy);
2236 }
2237 return Builder.finalizeTemplateArgs(CD);
2238}
2239
2241 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2242 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
2243 return BuiltinTypeMethodBuilder(*this, "IncrementCounter", UnsignedIntTy)
2244 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
2245 PH::CounterHandle, getConstantIntExpr(1))
2246 .finalize();
2247}
2248
2250 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2251 QualType UnsignedIntTy = SemaRef.getASTContext().UnsignedIntTy;
2252 return BuiltinTypeMethodBuilder(*this, "DecrementCounter", UnsignedIntTy)
2253 .callBuiltin("__builtin_hlsl_buffer_update_counter", UnsignedIntTy,
2254 PH::CounterHandle, getConstantIntExpr(-1))
2255 .finalize();
2256}
2257
2260 QualType ReturnTy) {
2261 assert(!Record->isCompleteDefinition() && "record is already complete");
2262 ASTContext &AST = SemaRef.getASTContext();
2263 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2264 bool NeedsTypedBuiltin = !ReturnTy.isNull();
2265
2266 // The empty QualType is a placeholder. The actual return type is set below.
2267 // All load methods will be const.
2268 BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), true);
2269
2270 if (!NeedsTypedBuiltin)
2271 ReturnTy = getHandleElementType();
2272 if (ReturnTy == AST.DependentTy)
2273 ReturnTy = MMB.addTemplateTypeParam("element_type");
2274 MMB.ReturnTy = ReturnTy;
2275
2276 MMB.addParam("Index", AST.UnsignedIntTy)
2277 .addParam("Status", AST.UnsignedIntTy,
2278 HLSLParamModifierAttr::Keyword_out);
2279
2280 if (NeedsTypedBuiltin)
2281 MMB.callBuiltin("__builtin_hlsl_resource_load_with_status_typed", ReturnTy,
2282 PH::Handle, PH::_0, PH::_1, ReturnTy);
2283 else
2284 MMB.callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy,
2285 PH::Handle, PH::_0, PH::_1);
2286
2287 return MMB.finalize();
2288}
2289
2291 DeclarationName &Name, bool IsConstReturn, bool IsRef, QualType IndexTy,
2292 QualType ElemTy) {
2293 assert(!Record->isCompleteDefinition() && "record is already complete");
2294 ASTContext &AST = SemaRef.getASTContext();
2295 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2296 bool NeedsTypedBuiltin = !ElemTy.isNull();
2297
2298 // The empty QualType is a placeholder. The actual return type is set below.
2299 // All access methods are const; none of them rebind the resource handle.
2300 BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), true);
2301
2302 if (!NeedsTypedBuiltin)
2303 ElemTy = getHandleElementType();
2304 if (ElemTy == AST.DependentTy)
2305 ElemTy = MMB.addTemplateTypeParam("element_type");
2306 QualType AddrSpaceElemTy =
2308 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
2309 QualType ReturnTy;
2310
2311 if (IsRef) {
2312 ReturnTy = AddrSpaceElemTy;
2313 if (IsConstReturn)
2314 ReturnTy.addConst();
2315 ReturnTy = AST.getLValueReferenceType(ReturnTy);
2316 } else {
2317 assert(!IsConstReturn && "There shouldn't be any resource methods with a "
2318 "const ref return value");
2319 ReturnTy = ElemTy;
2320 }
2321 MMB.ReturnTy = ReturnTy;
2322
2323 MMB.addParam("Index", IndexTy);
2324
2325 if (NeedsTypedBuiltin)
2326 MMB.callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
2327 PH::Handle, PH::_0, ElemTy);
2328 else
2329 MMB.callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
2330 PH::_0);
2331
2332 return MMB.dereference(PH::LastStmt).finalize();
2333}
2334
2337 QualType ValueTy) {
2338 assert(!Record->isCompleteDefinition() && "record is already complete");
2339 ASTContext &AST = SemaRef.getASTContext();
2340 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2341
2342 BuiltinTypeMethodBuilder MMB(*this, Name, AST.VoidTy, IsConst);
2343
2344 if (ValueTy == AST.DependentTy)
2345 ValueTy = MMB.addTemplateTypeParam("element_type");
2346 QualType AddrSpaceElemTy =
2348 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
2349
2350 return MMB.addParam("Index", AST.UnsignedIntTy)
2351 .addParam("Value", ValueTy)
2352 .callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
2353 PH::Handle, PH::_0, ValueTy)
2354 .dereference(PH::LastStmt)
2355 .assign(PH::LastStmt, PH::_1)
2356 .finalize();
2357}
2358
2360 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2361 ASTContext &AST = SemaRef.getASTContext();
2362 QualType ElemTy = getHandleElementType();
2363 QualType AddrSpaceElemTy =
2365 return BuiltinTypeMethodBuilder(*this, "Append", AST.VoidTy)
2366 .addParam("value", ElemTy)
2367 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
2368 PH::CounterHandle, getConstantIntExpr(1))
2369 .callBuiltin("__builtin_hlsl_resource_getpointer",
2370 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
2371 PH::LastStmt)
2372 .dereference(PH::LastStmt)
2373 .assign(PH::LastStmt, PH::_0)
2374 .finalize();
2375}
2376
2378 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2379 ASTContext &AST = SemaRef.getASTContext();
2380 QualType ElemTy = getHandleElementType();
2381 QualType AddrSpaceElemTy =
2383 return BuiltinTypeMethodBuilder(*this, "Consume", ElemTy)
2384 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
2385 PH::CounterHandle, getConstantIntExpr(-1))
2386 .callBuiltin("__builtin_hlsl_resource_getpointer",
2387 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
2388 PH::LastStmt)
2389 .dereference(PH::LastStmt)
2390 .finalize();
2391}
2392
2395 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
2396 ASTContext &AST = SemaRef.getASTContext();
2397 QualType UIntTy = AST.UnsignedIntTy;
2398
2399 QualType HandleTy = getResourceHandleField()->getType();
2400 auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr());
2401
2402 // Structured buffers except {RW}ByteAddressBuffer have overload
2403 // GetDimensions(out uint numStructs, out uint stride).
2404 if (AttrResTy->getAttrs().RawBuffer &&
2405 AttrResTy->getContainedType() != AST.Char8Ty) {
2406 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
2407 .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out)
2408 .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out)
2409 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
2410 PH::Handle, PH::_0)
2411 .callBuiltin("__builtin_hlsl_resource_getstride", QualType(),
2412 PH::Handle, PH::_1)
2413 .finalize();
2414 }
2415
2416 // Typed buffers and {RW}ByteAddressBuffer have overload
2417 // GetDimensions(out uint dim).
2418 return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
2419 .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out)
2420 .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
2421 PH::Handle, PH::_0)
2422 .finalize();
2423}
2424
2425} // namespace hlsl
2426} // 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:223
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:3195
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
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:2727
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:5104
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:1187
Represents a C++ constructor within a class.
Definition DeclCXX.h:2633
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:3016
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:3281
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
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:2502
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:133
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:1592
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:1466
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1276
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:494
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1641
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:4165
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:3195
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3431
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:4697
FriendDecl - Represents the declaration of a friend entity, which can be a function,...
Definition DeclFriend.h:45
static FriendDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, SourceLocation FriendL, SourceLocation EllipsisLoc={})
Represents a function declaration or definition.
Definition Decl.h:2027
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2238
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:4593
ExtParameterInfo withABI(ParameterABI kind) const
Definition TypeBase.h:4607
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:2079
static ImplicitConceptSpecializationDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation SL, ArrayRef< TemplateArgument > ConvertedArgs)
Describes an C or C++ initializer list.
Definition Expr.h:5305
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:981
Represents the results of name lookup.
Definition Lookup.h:147
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3370
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:3431
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:2934
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType withConst() const
Definition TypeBase.h:1174
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1171
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:8447
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:321
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:869
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1142
@ 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:940
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
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:3853
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, int D, int P, IdentifierInfo *Id, bool Typename, bool ParameterPack, bool HasTypeConstraint=false, UnsignedOrNone NumExpanded=std::nullopt)
A container of type source information.
Definition TypeBase.h:8418
The base class of the type hierarchy.
Definition TypeBase.h:1875
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:9344
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:8823
bool isRecordType() const
Definition TypeBase.h:8811
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:5161
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
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:4239
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 & addSampleGradMethods(ResourceDimension Dim, bool IsArray=false)
BuiltinTypeDeclBuilder & addCopyAssignmentOperator(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeDeclBuilder & addGatherCmpMethods(ResourceDimension Dim, bool IsArray=false)
BuiltinTypeDeclBuilder & addGetDimensionsMethodForBuffer()
BuiltinTypeDeclBuilder & addConstantBufferConversionToType()
BuiltinTypeDeclBuilder & addTextureLoadMethods(ResourceDimension Dim, bool IsArray=false)
BuiltinTypeDeclBuilder & addSampleBiasMethods(ResourceDimension Dim, bool IsArray=false)
BuiltinTypeDeclBuilder & addBufferHandles(ResourceClass RC, bool IsROV, bool RawBuffer, bool HasCounter, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addByteAddressBufferStoreMethods()
BuiltinTypeDeclBuilder & addSampleMethods(ResourceDimension Dim, bool IsArray=false)
BuiltinTypeDeclBuilder & addArraySubscriptOperators(ResourceDimension Dim=ResourceDimension::Unknown, bool IsArray=false)
BuiltinTypeDeclBuilder & addSampleLevelMethods(ResourceDimension Dim, bool IsArray=false)
BuiltinTypeDeclBuilder & addCopyConstructor(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeDeclBuilder & addTextureHandle(ResourceClass RC, bool IsROV, bool IsArray, ResourceDimension RD, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addLoadWithStatusFunction(DeclarationName &Name, QualType ReturnTy=QualType())
BuiltinTypeDeclBuilder & addSampleCmpMethods(ResourceDimension Dim, bool IsArray=false)
BuiltinTypeDeclBuilder & addMipsMember(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addByteAddressBufferLoadMethods()
BuiltinTypeDeclBuilder & addStaticInitializationFunctions(bool HasCounter)
BuiltinTypeDeclBuilder & addGatherMethods(ResourceDimension Dim, bool IsArray=false)
BuiltinTypeDeclBuilder & addCalculateLodMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addGetDimensionsMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addSimpleTemplateParams(ArrayRef< StringRef > Names, ConceptDecl *CD=nullptr)
BuiltinTypeDeclBuilder & addSampleCmpLevelZeroMethods(ResourceDimension Dim, bool IsArray=false)
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:1772
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)