clang 23.0.0git
HLSLExternalSemaSource.cpp
Go to the documentation of this file.
1//===--- HLSLExternalSemaSource.cpp - HLSL Sema Source --------------------===//
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//
10//===----------------------------------------------------------------------===//
11
15#include "clang/AST/Attr.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclCXX.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/Type.h"
24#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Sema.h"
26#include "clang/Sema/SemaHLSL.h"
28#include "llvm/ADT/STLExtras.h"
29#include "llvm/ADT/SmallVector.h"
30
31using namespace clang;
32using namespace llvm::hlsl;
33
35
37 SemaPtr = &S;
38 ASTContext &AST = SemaPtr->getASTContext();
39 // If the translation unit has external storage force external decls to load.
42
43 IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier);
45 NamespaceDecl *PrevDecl = nullptr;
47 PrevDecl = Result.getAsSingle<NamespaceDecl>();
48 HLSLNamespace = NamespaceDecl::Create(
49 AST, AST.getTranslationUnitDecl(), /*Inline=*/false, SourceLocation(),
50 SourceLocation(), &HLSL, PrevDecl, /*Nested=*/false);
51 HLSLNamespace->setImplicit(true);
52 HLSLNamespace->setHasExternalLexicalStorage();
53 AST.getTranslationUnitDecl()->addDecl(HLSLNamespace);
54
55 // Force external decls in the HLSL namespace to load from the PCH.
56 (void)HLSLNamespace->getCanonicalDecl()->decls_begin();
57 defineTrivialHLSLTypes();
58 defineHLSLTypesWithForwardDeclarations();
59 defineHLSLAtomicIntrinsics();
60
61 // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's
62 // built in types inside a namespace, but we are planning to change that in
63 // the near future. In order to be source compatible older versions of HLSL
64 // will need to implicitly use the hlsl namespace. For now in clang everything
65 // will get added to the namespace, and we can remove the using directive for
66 // future language versions to match HLSL's evolution.
69 NestedNameSpecifierLoc(), SourceLocation(), HLSLNamespace,
71
73}
74
75void HLSLExternalSemaSource::defineHLSLVectorAlias() {
76 ASTContext &AST = SemaPtr->getASTContext();
77
78 llvm::SmallVector<NamedDecl *> TemplateParams;
79
80 auto *TypeParam = TemplateTypeParmDecl::Create(
81 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0,
82 &AST.Idents.get("element", tok::TokenKind::identifier), false, false);
83 TypeParam->setDefaultArgument(
86
87 TemplateParams.emplace_back(TypeParam);
88
89 auto *SizeParam = NonTypeTemplateParmDecl::Create(
90 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
91 &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy,
92 false, AST.getTrivialTypeSourceInfo(AST.IntTy));
93 llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4);
94 TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy,
95 /*IsDefaulted=*/true);
96 SizeParam->setDefaultArgument(AST, SemaPtr->getTrivialTemplateArgumentLoc(
98 TemplateParams.emplace_back(SizeParam);
99
100 auto *ParamList =
102 TemplateParams, SourceLocation(), nullptr);
103
104 IdentifierInfo &II = AST.Idents.get("vector", tok::TokenKind::identifier);
105
107 AST.getTemplateTypeParmType(0, 0, false, TypeParam),
109 AST, NestedNameSpecifierLoc(), SourceLocation(), SizeParam, false,
110 DeclarationNameInfo(SizeParam->getDeclName(), SourceLocation()),
111 AST.IntTy, VK_LValue),
113
114 auto *Record = TypeAliasDecl::Create(AST, HLSLNamespace, SourceLocation(),
115 SourceLocation(), &II,
116 AST.getTrivialTypeSourceInfo(AliasType));
117 Record->setImplicit(true);
118
119 auto *Template =
120 TypeAliasTemplateDecl::Create(AST, HLSLNamespace, SourceLocation(),
121 Record->getIdentifier(), ParamList, Record);
122
123 Record->setDescribedAliasTemplate(Template);
124 Template->setImplicit(true);
125 Template->setLexicalDeclContext(Record->getDeclContext());
126 HLSLNamespace->addDecl(Template);
127}
128
129void HLSLExternalSemaSource::defineHLSLMatrixAlias() {
130 ASTContext &AST = SemaPtr->getASTContext();
131 llvm::SmallVector<NamedDecl *> TemplateParams;
132
133 auto *TypeParam = TemplateTypeParmDecl::Create(
134 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0,
135 &AST.Idents.get("element", tok::TokenKind::identifier), false, false);
136 TypeParam->setDefaultArgument(
137 AST, SemaPtr->getTrivialTemplateArgumentLoc(
139
140 TemplateParams.emplace_back(TypeParam);
141
142 // these should be 64 bit to be consistent with other clang matrices.
143 auto *RowsParam = NonTypeTemplateParmDecl::Create(
144 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
145 &AST.Idents.get("rows_count", tok::TokenKind::identifier), AST.IntTy,
146 false, AST.getTrivialTypeSourceInfo(AST.IntTy));
147 llvm::APInt RVal(AST.getIntWidth(AST.IntTy), 4);
148 TemplateArgument RDefault(AST, llvm::APSInt(std::move(RVal)), AST.IntTy,
149 /*IsDefaulted=*/true);
150 RowsParam->setDefaultArgument(
151 AST, SemaPtr->getTrivialTemplateArgumentLoc(RDefault, AST.IntTy,
152 SourceLocation()));
153 TemplateParams.emplace_back(RowsParam);
154
155 auto *ColsParam = NonTypeTemplateParmDecl::Create(
156 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 2,
157 &AST.Idents.get("cols_count", tok::TokenKind::identifier), AST.IntTy,
158 false, AST.getTrivialTypeSourceInfo(AST.IntTy));
159 llvm::APInt CVal(AST.getIntWidth(AST.IntTy), 4);
160 TemplateArgument CDefault(AST, llvm::APSInt(std::move(CVal)), AST.IntTy,
161 /*IsDefaulted=*/true);
162 ColsParam->setDefaultArgument(
163 AST, SemaPtr->getTrivialTemplateArgumentLoc(CDefault, AST.IntTy,
164 SourceLocation()));
165 TemplateParams.emplace_back(ColsParam);
166
167 const unsigned MaxMatDim = SemaPtr->getLangOpts().MaxMatrixDimension;
168
169 auto *MaxRow = IntegerLiteral::Create(
170 AST, llvm::APInt(AST.getIntWidth(AST.IntTy), MaxMatDim), AST.IntTy,
172 auto *MaxCol = IntegerLiteral::Create(
173 AST, llvm::APInt(AST.getIntWidth(AST.IntTy), MaxMatDim), AST.IntTy,
175
176 auto *RowsRef = DeclRefExpr::Create(
177 AST, NestedNameSpecifierLoc(), SourceLocation(), RowsParam,
178 /*RefersToEnclosingVariableOrCapture*/ false,
179 DeclarationNameInfo(RowsParam->getDeclName(), SourceLocation()),
180 AST.IntTy, VK_LValue);
181 auto *ColsRef = DeclRefExpr::Create(
182 AST, NestedNameSpecifierLoc(), SourceLocation(), ColsParam,
183 /*RefersToEnclosingVariableOrCapture*/ false,
184 DeclarationNameInfo(ColsParam->getDeclName(), SourceLocation()),
185 AST.IntTy, VK_LValue);
186
187 auto *RowsLE = BinaryOperator::Create(AST, RowsRef, MaxRow, BO_LE, AST.BoolTy,
190 auto *ColsLE = BinaryOperator::Create(AST, ColsRef, MaxCol, BO_LE, AST.BoolTy,
193
195 AST, RowsLE, ColsLE, BO_LAnd, AST.BoolTy, VK_PRValue, OK_Ordinary,
197
198 auto *ParamList = TemplateParameterList::Create(
199 AST, SourceLocation(), SourceLocation(), TemplateParams, SourceLocation(),
201
202 IdentifierInfo &II = AST.Idents.get("matrix", tok::TokenKind::identifier);
203
205 AST.getTemplateTypeParmType(0, 0, false, TypeParam),
207 AST, NestedNameSpecifierLoc(), SourceLocation(), RowsParam, false,
208 DeclarationNameInfo(RowsParam->getDeclName(), SourceLocation()),
209 AST.IntTy, VK_LValue),
211 AST, NestedNameSpecifierLoc(), SourceLocation(), ColsParam, false,
212 DeclarationNameInfo(ColsParam->getDeclName(), SourceLocation()),
213 AST.IntTy, VK_LValue),
215
216 auto *Record = TypeAliasDecl::Create(AST, HLSLNamespace, SourceLocation(),
217 SourceLocation(), &II,
218 AST.getTrivialTypeSourceInfo(AliasType));
219 Record->setImplicit(true);
220
221 auto *Template =
222 TypeAliasTemplateDecl::Create(AST, HLSLNamespace, SourceLocation(),
223 Record->getIdentifier(), ParamList, Record);
224
225 Record->setDescribedAliasTemplate(Template);
226 Template->setImplicit(true);
227 Template->setLexicalDeclContext(Record->getDeclContext());
228 HLSLNamespace->addDecl(Template);
229}
230
231void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
232 defineHLSLVectorAlias();
233 defineHLSLMatrixAlias();
234}
235
236/// Set up common members and attributes for buffer types
238 ResourceClass RC, bool IsROV,
239 bool RawBuffer, bool HasCounter) {
241 .addBufferHandles(RC, IsROV, RawBuffer, HasCounter)
246}
247
248/// Set up common members and attributes for sampler types
257
258/// Set up common members and attributes for texture types
282
283// Add a partial specialization for a template. The `TextureTemplate` is
284// `Texture<element_type>`, and it will be specialized for vectors:
285// `Texture<vector<element_type, element_count>>`.
288 ClassTemplateDecl *TextureTemplate) {
289 ASTContext &AST = S.getASTContext();
290
291 // Create the template parameters: element_type and element_count.
292 auto *ElementType = TemplateTypeParmDecl::Create(
293 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0,
294 &AST.Idents.get("element_type"), false, false);
295 auto *ElementCount = NonTypeTemplateParmDecl::Create(
296 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
297 &AST.Idents.get("element_count"), AST.IntTy, false,
299
300 auto *TemplateParams = TemplateParameterList::Create(
301 AST, SourceLocation(), SourceLocation(), {ElementType, ElementCount},
302 SourceLocation(), nullptr);
303
304 // Create the dependent vector type: vector<element_type, element_count>.
306 AST.getTemplateTypeParmType(0, 0, false, ElementType),
308 AST, NestedNameSpecifierLoc(), SourceLocation(), ElementCount, false,
309 DeclarationNameInfo(ElementCount->getDeclName(), SourceLocation()),
310 AST.IntTy, VK_LValue),
312
313 // Create the partial specialization declaration.
314 QualType CanonInjectedTST =
318
320 AST, TagDecl::TagKind::Class, HLSLNamespace, SourceLocation(),
321 SourceLocation(), TemplateParams, TextureTemplate,
323 CanQualType::CreateUnsafe(CanonInjectedTST), nullptr);
324
325 // Set the template arguments as written.
327 TemplateArgumentLoc ArgLoc =
329 TemplateArgumentListInfo ArgsInfo =
331 ArgsInfo.addArgument(ArgLoc);
332 PartialSpec->setTemplateArgsAsWritten(
334
335 PartialSpec->setImplicit(true);
336 PartialSpec->setLexicalDeclContext(HLSLNamespace);
337 PartialSpec->setHasExternalLexicalStorage();
338
339 // Add the partial specialization to the namespace and the class template.
340 HLSLNamespace->addDecl(PartialSpec);
341 TextureTemplate->AddPartialSpecialization(PartialSpec, nullptr);
342
343 return PartialSpec;
344}
345
346// This function is responsible for constructing the constraint expression for
347// this concept:
348// template<typename T> concept is_typed_resource_element_compatible =
349// __is_typed_resource_element_compatible<T>;
352 ASTContext &Context = S.getASTContext();
353
354 // Obtain the QualType for 'bool'
355 QualType BoolTy = Context.BoolTy;
356
357 // Create a QualType that points to this TemplateTypeParmDecl
358 QualType TType = Context.getTypeDeclType(T);
359
360 // Create a TypeSourceInfo for the template type parameter 'T'
361 TypeSourceInfo *TTypeSourceInfo =
362 Context.getTrivialTypeSourceInfo(TType, NameLoc);
363
364 TypeTraitExpr *TypedResExpr = TypeTraitExpr::Create(
365 Context, BoolTy, NameLoc, UTT_IsTypedResourceElementCompatible,
366 {TTypeSourceInfo}, NameLoc, true);
367
368 return TypedResExpr;
369}
370
371// This function is responsible for constructing the constraint expression for
372// this concept:
373// template<typename T> concept is_constant_buffer_element_compatible =
374// std::is_class_v<T> && !__is_intangible(T);
376 SourceLocation NameLoc,
378 ASTContext &Context = S.getASTContext();
379
380 // Obtain the QualType for 'bool'
381 QualType BoolTy = Context.BoolTy;
382
383 // Create a QualType that points to this TemplateTypeParmDecl
384 QualType TType = Context.getTypeDeclType(T);
385
386 // Create a TypeSourceInfo for the template type parameter 'T'
387 TypeSourceInfo *TTypeSourceInfo =
388 Context.getTrivialTypeSourceInfo(TType, NameLoc);
389
391 Context, BoolTy, NameLoc, UTT_IsConstantBufferElementCompatible,
392 {TTypeSourceInfo}, NameLoc, true);
393
394 return ResExpr;
395}
396
397// This function is responsible for constructing the constraint expression for
398// this concept:
399// template<typename T> concept is_structured_resource_element_compatible =
400// !__is_intangible<T> && sizeof(T) >= 1;
402 SourceLocation NameLoc,
404 ASTContext &Context = S.getASTContext();
405
406 // Obtain the QualType for 'bool'
407 QualType BoolTy = Context.BoolTy;
408
409 // Create a QualType that points to this TemplateTypeParmDecl
410 QualType TType = Context.getTypeDeclType(T);
411
412 // Create a TypeSourceInfo for the template type parameter 'T'
413 TypeSourceInfo *TTypeSourceInfo =
414 Context.getTrivialTypeSourceInfo(TType, NameLoc);
415
416 TypeTraitExpr *IsIntangibleExpr =
417 TypeTraitExpr::Create(Context, BoolTy, NameLoc, UTT_IsIntangibleType,
418 {TTypeSourceInfo}, NameLoc, true);
419
420 // negate IsIntangibleExpr
421 UnaryOperator *NotIntangibleExpr = UnaryOperator::Create(
422 Context, IsIntangibleExpr, UO_LNot, BoolTy, VK_LValue, OK_Ordinary,
423 NameLoc, false, FPOptionsOverride());
424
425 // element types also may not be of 0 size
426 UnaryExprOrTypeTraitExpr *SizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
427 UETT_SizeOf, TTypeSourceInfo, BoolTy, NameLoc, NameLoc);
428
429 // Create a BinaryOperator that checks if the size of the type is not equal to
430 // 1 Empty structs have a size of 1 in HLSL, so we need to check for that
432 Context, llvm::APInt(Context.getTypeSize(Context.getSizeType()), 1, true),
433 Context.getSizeType(), NameLoc);
434
435 BinaryOperator *SizeGEQOneExpr =
436 BinaryOperator::Create(Context, SizeOfExpr, rhs, BO_GE, BoolTy, VK_LValue,
437 OK_Ordinary, NameLoc, FPOptionsOverride());
438
439 // Combine the two constraints
441 Context, NotIntangibleExpr, SizeGEQOneExpr, BO_LAnd, BoolTy, VK_LValue,
442 OK_Ordinary, NameLoc, FPOptionsOverride());
443
444 return CombinedExpr;
445}
446
448
450 HLSLBufferType BT) {
451 ASTContext &Context = S.getASTContext();
452 DeclContext *DC = NSD->getDeclContext();
453 SourceLocation DeclLoc = SourceLocation();
454
455 IdentifierInfo &ElementTypeII = Context.Idents.get("element_type");
457 Context, NSD->getDeclContext(), DeclLoc, DeclLoc,
458 /*D=*/0,
459 /*P=*/0,
460 /*Id=*/&ElementTypeII,
461 /*Typename=*/true,
462 /*ParameterPack=*/false);
463
464 T->setDeclContext(DC);
465 T->setReferenced();
466
467 // Create and Attach Template Parameter List to ConceptDecl
469 Context, DeclLoc, DeclLoc, {T}, DeclLoc, nullptr);
470
471 DeclarationName DeclName;
472 Expr *ConstraintExpr = nullptr;
473
474 switch (BT) {
476 DeclName = DeclarationName(
477 &Context.Idents.get("__is_typed_resource_element_compatible"));
478 ConstraintExpr = constructTypedBufferConstraintExpr(S, DeclLoc, T);
479 break;
481 DeclName = DeclarationName(
482 &Context.Idents.get("__is_structured_resource_element_compatible"));
483 ConstraintExpr = constructStructuredBufferConstraintExpr(S, DeclLoc, T);
484 break;
486 DeclName = DeclarationName(
487 &Context.Idents.get("__is_constant_buffer_element_compatible"));
488 ConstraintExpr = constructConstantBufferConstraintExpr(S, DeclLoc, T);
489 break;
490 }
491
492 // Create a ConceptDecl
493 ConceptDecl *CD =
494 ConceptDecl::Create(Context, NSD->getDeclContext(), DeclLoc, DeclName,
495 ConceptParams, ConstraintExpr);
496
497 // Attach the template parameter list to the ConceptDecl
498 CD->setTemplateParameters(ConceptParams);
499
500 // Add the concept declaration to the Translation Unit Decl
501 NSD->getDeclContext()->addDecl(CD);
502
503 return CD;
504}
505
506void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
507 ASTContext &AST = SemaPtr->getASTContext();
508 CXXRecordDecl *Decl;
509 ConceptDecl *TypedBufferConcept = constructBufferConceptDecl(
510 *SemaPtr, HLSLNamespace, HLSLBufferType::Typed);
511 ConceptDecl *StructuredBufferConcept = constructBufferConceptDecl(
512 *SemaPtr, HLSLNamespace, HLSLBufferType::Structured);
513 ConceptDecl *ConstantBufferConcept = constructBufferConceptDecl(
514 *SemaPtr, HLSLNamespace, HLSLBufferType::Constant);
515
516 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConstantBuffer")
517 .addSimpleTemplateParams({"element_type"}, ConstantBufferConcept)
518 .finalizeForwardDeclaration();
519
520 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
521 setupBufferType(Decl, *SemaPtr, ResourceClass::CBuffer, /*IsROV=*/false,
522 /*RawBuffer=*/false, /*HasCounter=*/false)
525 });
526
527 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "Buffer")
528 .addSimpleTemplateParams({"element_type"}, TypedBufferConcept)
529 .finalizeForwardDeclaration();
530
531 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
532 setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
533 /*RawBuffer=*/false, /*HasCounter=*/false)
538 });
539
540 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
541 .addSimpleTemplateParams({"element_type"}, TypedBufferConcept)
542 .finalizeForwardDeclaration();
543
544 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
545 setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
546 /*RawBuffer=*/false, /*HasCounter=*/false)
551 });
552
553 Decl =
554 BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer")
555 .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept)
556 .finalizeForwardDeclaration();
557 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
558 setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/true,
559 /*RawBuffer=*/false, /*HasCounter=*/false)
564 });
565
566 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer")
567 .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept)
568 .finalizeForwardDeclaration();
569 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
570 setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
571 /*RawBuffer=*/true, /*HasCounter=*/false)
576 });
577
578 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWStructuredBuffer")
579 .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept)
580 .finalizeForwardDeclaration();
581 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
582 setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
583 /*RawBuffer=*/true, /*HasCounter=*/true)
590 });
591
592 Decl =
593 BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "AppendStructuredBuffer")
594 .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept)
595 .finalizeForwardDeclaration();
596 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
597 setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
598 /*RawBuffer=*/true, /*HasCounter=*/true)
602 });
603
604 Decl =
605 BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConsumeStructuredBuffer")
606 .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept)
607 .finalizeForwardDeclaration();
608 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
609 setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
610 /*RawBuffer=*/true, /*HasCounter=*/true)
614 });
615
616 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
617 "RasterizerOrderedStructuredBuffer")
618 .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept)
619 .finalizeForwardDeclaration();
620 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
621 setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/true,
622 /*RawBuffer=*/true, /*HasCounter=*/true)
629 });
630
631 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ByteAddressBuffer")
632 .finalizeForwardDeclaration();
633 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
634 setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
635 /*RawBuffer=*/true, /*HasCounter=*/false)
639 });
640 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWByteAddressBuffer")
641 .finalizeForwardDeclaration();
642 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
643 setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
644 /*RawBuffer=*/true, /*HasCounter=*/false)
649 });
650 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
651 "RasterizerOrderedByteAddressBuffer")
652 .finalizeForwardDeclaration();
653 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
654 setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/true,
655 /*RawBuffer=*/true, /*HasCounter=*/false)
658 });
659
660 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "SamplerState")
661 .finalizeForwardDeclaration();
662 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
663 setupSamplerType(Decl, *SemaPtr).completeDefinition();
664 });
665
666 Decl =
667 BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "SamplerComparisonState")
668 .finalizeForwardDeclaration();
669 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
670 setupSamplerType(Decl, *SemaPtr).completeDefinition();
671 });
672
673 QualType Float4Ty = AST.getExtVectorType(AST.FloatTy, 4);
674 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "Texture2D")
675 .addSimpleTemplateParams({"element_type"}, {Float4Ty},
676 TypedBufferConcept)
677 .finalizeForwardDeclaration();
678
679 onCompletion(Decl, [this](CXXRecordDecl *Decl) {
680 setupTextureType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
681 ResourceDimension::Dim2D)
683 });
684
685 auto *PartialSpec = addVectorTexturePartialSpecialization(
686 *SemaPtr, HLSLNamespace, Decl->getDescribedClassTemplate());
687 onCompletion(PartialSpec, [this](CXXRecordDecl *Decl) {
688 setupTextureType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
689 ResourceDimension::Dim2D)
691 });
692}
693
694// Build a single overload of an HLSL atomic intrinsic in the hlsl namespace.
695// `dest` is an address-space-qualified reference; `original_value` (when
696// present) is a plain reference. The synthesized FunctionDecl aliases the
697// underlying clang builtin via BuiltinAliasAttr.
698static void buildAtomicOverload(Sema &S, NamespaceDecl *NS, StringRef FuncName,
699 StringRef BuiltinName, QualType ElemTy,
700 LangAS DestAS, bool ThreeArg) {
701 ASTContext &AST = S.getASTContext();
702
703 QualType DestTy =
704 AST.getLValueReferenceType(AST.getAddrSpaceQualType(ElemTy, DestAS));
705 QualType OrigRefTy = AST.getLValueReferenceType(ElemTy);
706
707 SmallVector<QualType, 3> ParamTypes;
708 ParamTypes.push_back(DestTy);
709 ParamTypes.push_back(ElemTy);
710 if (ThreeArg)
711 ParamTypes.push_back(OrigRefTy);
712
714 QualType FuncTy = AST.getFunctionType(AST.VoidTy, ParamTypes, EPI);
715 auto *TSInfo = AST.getTrivialTypeSourceInfo(FuncTy, SourceLocation());
716
717 IdentifierInfo &FuncII = AST.Idents.get(FuncName, tok::TokenKind::identifier);
718 DeclarationName FuncDeclName(&FuncII);
719
721 AST, NS, SourceLocation(), SourceLocation(), FuncDeclName, FuncTy, TSInfo,
722 SC_Extern, /*UsesFPIntrin=*/false, /*isInlineSpecified=*/false,
723 /*hasWrittenPrototype=*/true);
724
725 constexpr const char *ParamNames[] = {"dest", "value", "original_value"};
727 unsigned I = 0;
728 for (auto [ParamType, ParamName] : llvm::zip(ParamTypes, ParamNames)) {
729 IdentifierInfo &PII = AST.Idents.get(ParamName, tok::TokenKind::identifier);
731 AST, FD, SourceLocation(), SourceLocation(), &PII, ParamType,
733 nullptr);
734 Parm->setScopeInfo(0, I++);
735 ParmDecls.push_back(Parm);
736 }
737 FD->setParams(ParmDecls);
738
739 IdentifierInfo &BuiltinII =
740 S.getPreprocessor().getIdentifierTable().get(BuiltinName);
741 FD->addAttr(BuiltinAliasAttr::CreateImplicit(AST, &BuiltinII));
742 FD->setImplicit();
743 NS->addDecl(FD);
744}
745
746// Synthesize the InterlockedAdd overload set: {int, uint, int64_t, uint64_t}
747// x {groupshared, device} x {2-arg, 3-arg}.
749 ASTContext &AST = S.getASTContext();
750 // HLSL: int64_t == long, uint64_t == unsigned long (see hlsl_basic_types.h).
751 QualType Elems[] = {AST.IntTy, AST.UnsignedIntTy, AST.LongTy,
752 AST.UnsignedLongTy};
754
755 for (QualType ElemTy : Elems)
756 for (LangAS AS : AddrSpaces)
757 for (bool ThreeArg : {false, true})
758 buildAtomicOverload(S, NS, "InterlockedAdd",
759 "__builtin_hlsl_interlocked_add", ElemTy, AS,
760 ThreeArg);
761}
762
763void HLSLExternalSemaSource::defineHLSLAtomicIntrinsics() {
764 defineHLSLInterlockedAdd(*SemaPtr, HLSLNamespace);
765}
766
767void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
768 CompletionFunction Fn) {
769 if (!Record->isCompleteDefinition())
770 Completions.insert(std::make_pair(Record->getCanonicalDecl(), Fn));
771}
772
774 if (!isa<CXXRecordDecl>(Tag))
775 return;
776 auto Record = cast<CXXRecordDecl>(Tag);
777
778 // If this is a specialization, we need to get the underlying templated
779 // declaration and complete that.
780 if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
782 ClassTemplateDecl *Template = TDecl->getSpecializedTemplate();
784 Template->getPartialSpecializations(Partials);
785 ClassTemplatePartialSpecializationDecl *MatchedPartial = nullptr;
786 for (auto *Partial : Partials) {
787 sema::TemplateDeductionInfo Info(TDecl->getLocation());
788 if (SemaPtr->DeduceTemplateArguments(Partial, TDecl->getTemplateArgs(),
789 Info) ==
791 MatchedPartial = Partial;
792 break;
793 }
794 }
795 if (MatchedPartial)
796 Record = MatchedPartial;
797 else
798 Record = Template->getTemplatedDecl();
799 }
800 }
801 Record = Record->getCanonicalDecl();
802 auto It = Completions.find(Record);
803 if (It == Completions.end())
804 return;
805 // Move out the callback and erase before invoking it: the callback can
806 // re-enter CompleteType and mutate Completions, which invalidates It under
807 // backward-shift deletion.
808 CompletionFunction Fn = std::move(It->second);
809 Completions.erase(It);
810 Fn(Record);
811}
Defines the clang::ASTContext interface.
Provides definitions for the various language-specific address spaces.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, ResourceClass RC, bool IsROV, bool RawBuffer, bool HasCounter)
Set up common members and attributes for buffer types.
static void defineHLSLInterlockedAdd(Sema &S, NamespaceDecl *NS)
static BuiltinTypeDeclBuilder setupSamplerType(CXXRecordDecl *Decl, Sema &S)
Set up common members and attributes for sampler types.
static void buildAtomicOverload(Sema &S, NamespaceDecl *NS, StringRef FuncName, StringRef BuiltinName, QualType ElemTy, LangAS DestAS, bool ThreeArg)
static Expr * constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc, TemplateTypeParmDecl *T)
static ConceptDecl * constructBufferConceptDecl(Sema &S, NamespaceDecl *NSD, HLSLBufferType BT)
static BuiltinTypeDeclBuilder setupTextureType(CXXRecordDecl *Decl, Sema &S, ResourceClass RC, bool IsROV, ResourceDimension Dim)
Set up common members and attributes for texture types.
static Expr * constructConstantBufferConstraintExpr(Sema &S, SourceLocation NameLoc, TemplateTypeParmDecl *T)
static ClassTemplatePartialSpecializationDecl * addVectorTexturePartialSpecialization(Sema &S, NamespaceDecl *HLSLNamespace, ClassTemplateDecl *TextureTemplate)
static Expr * constructStructuredBufferConstraintExpr(Sema &S, SourceLocation NameLoc, TemplateTypeParmDecl *T)
llvm::MachO::Record Record
Definition MachO.h:31
Defines the clang::Preprocessor interface.
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
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
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getDependentSizedMatrixType(QualType ElementType, Expr *RowExpr, Expr *ColumnExpr, SourceLocation AttrLoc) const
Return the unique reference to the matrix type of the specified element type and size.
CanQualType LongTy
unsigned getIntWidth(QualType T) const
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
CanQualType FloatTy
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
IdentifierTable & Idents
Definition ASTContext.h:802
CanQualType BoolTy
CanQualType UnsignedLongTy
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType IntTy
CanQualType VoidTy
CanQualType UnsignedIntTy
QualType getTemplateSpecializationType(ElaboratedTypeKeyword Keyword, TemplateName T, ArrayRef< TemplateArgument > SpecifiedArgs, ArrayRef< TemplateArgument > CanonicalArgs, QualType Underlying=QualType()) const
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
QualType getTemplateTypeParmType(int Depth, int Index, bool ParameterPack, TemplateTypeParmDecl *ParmDecl=nullptr) const
Retrieve the template type parameter type for a template parameter or parameter pack with the given d...
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 ...
QualType getDependentSizedExtVectorType(QualType VectorType, Expr *SizeExpr, SourceLocation AttrLoc) const
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4041
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
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
static CanQual< Type > CreateUnsafe(QualType Other)
Declaration of a class template.
void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D, void *InsertPos)
Insert the specified partial specialization knowing that it is not already in.
static ClassTemplatePartialSpecializationDecl * Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, ArrayRef< TemplateArgument > Args, CanQualType CanonInjectedTST, ClassTemplatePartialSpecializationDecl *PrevDecl)
Declaration of a C++20 concept.
static ConceptDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, Expr *ConstraintExpr=nullptr)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1462
void addDecl(Decl *D)
Add the declaration D into this context.
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Definition DeclBase.h:2701
decl_iterator decls_begin() const
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
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void addAttr(Attr *A)
void setImplicit(bool I=true)
Definition DeclBase.h:602
DeclContext * getDeclContext()
Definition DeclBase.h:456
The name of a declaration.
This represents one expression.
Definition Expr.h:112
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Definition Decl.h:2018
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
Definition Decl.h:2207
void CompleteType(TagDecl *Tag) override
Complete an incomplete HLSL builtin type.
void InitializeSema(Sema &S) override
Initialize the semantic source with the Sema instance being used to perform semantic analysis on the ...
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 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
Represent a C++ namespace.
Definition Decl.h:592
static NamespaceDecl * Create(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested)
Definition DeclCXX.cpp:3362
A C++ nested-name-specifier augmented with source location information.
static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, int D, int P, const IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo)
Represents a parameter to a function.
Definition Decl.h:1808
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
Definition Decl.h:1841
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:2931
IdentifierTable & getIdentifierTable()
A (possibly-)qualified type.
Definition TypeBase.h:937
C++2a [expr.prim.req]: A requires-expression provides a concise way to express requirements on templa...
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
@ LookupNamespaceName
Look up a namespace name within a C++ using directive or namespace alias definition,...
Definition Sema.h:9443
Preprocessor & getPreprocessor() const
Definition Sema.h:938
ASTContext & getASTContext() const
Definition Sema.h:939
const LangOptions & getLangOpts() const
Definition Sema.h:932
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3739
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
Location wrapper for a TemplateArgument.
Represents a template argument.
void setTemplateParameters(TemplateParameterList *TParams)
Represents a C++ template name within the type system.
Stores a list of template parameters for a TemplateDecl and its derived classes.
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)
static TypeAliasDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, TypeSourceInfo *TInfo)
Definition Decl.cpp:5811
static TypeAliasTemplateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl)
Create a function template node.
A container of type source information.
Definition TypeBase.h:8418
A type trait used in the implementation of various C++11 and Library TR1 trait templates.
Definition ExprCXX.h:2900
static TypeTraitExpr * Create(const ASTContext &C, QualType T, SourceLocation Loc, TypeTrait Kind, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool Value)
Create a new type trait expression.
Definition ExprCXX.cpp:1907
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition Expr.h:2628
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2247
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
Represents a C++ using-declaration.
Definition DeclCXX.h:3609
static UsingDirectiveDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation NamespaceLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor)
Definition DeclCXX.cpp:3318
Represents a GCC generic vector type.
Definition TypeBase.h:4239
BuiltinTypeDeclBuilder & addDefaultHandleConstructor(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeDeclBuilder & addCopyAssignmentOperator(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeDeclBuilder & addArraySubscriptOperators(ResourceDimension Dim=ResourceDimension::Unknown)
BuiltinTypeDeclBuilder & addSampleGradMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addGetDimensionsMethodForBuffer()
BuiltinTypeDeclBuilder & addGatherCmpMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addConstantBufferConversionToType()
BuiltinTypeDeclBuilder & addSampleBiasMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addBufferHandles(ResourceClass RC, bool IsROV, bool RawBuffer, bool HasCounter, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addByteAddressBufferStoreMethods()
BuiltinTypeDeclBuilder & addTextureHandle(ResourceClass RC, bool IsROV, ResourceDimension RD, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addCopyConstructor(AccessSpecifier Access=AccessSpecifier::AS_public)
BuiltinTypeDeclBuilder & addTextureLoadMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addSampleLevelMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addMipsMember(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addByteAddressBufferLoadMethods()
BuiltinTypeDeclBuilder & addSampleMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addStaticInitializationFunctions(bool HasCounter)
BuiltinTypeDeclBuilder & addCalculateLodMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addGetDimensionsMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addSampleCmpLevelZeroMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addGatherMethods(ResourceDimension Dim)
BuiltinTypeDeclBuilder & addSampleCmpMethods(ResourceDimension Dim)
Provides information about an attempted template argument deduction, whose success or failure was des...
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:152
@ SC_Extern
Definition Specifiers.h:252
@ SC_None
Definition Specifiers.h:251
@ Result
The result type of a method or function.
Definition TypeBase.h:905
@ Template
We are parsing a template declaration.
Definition Parser.h:81
LangAS
Defines the address space values used by the address space qualifier of QualType.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:136
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:140
@ Success
Template argument deduction was successful.
Definition Sema.h:371
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:5981
static const ASTTemplateArgumentListInfo * Create(const ASTContext &C, const TemplateArgumentListInfo &List)
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
Extra information about a function prototype.
Definition TypeBase.h:5456