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
12#include "clang/Sema/HLSLExternalSemaSource.h"
13#include "HLSLBuiltinTypeDeclBuilder.h"
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/Attr.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/Expr.h"
19#include "clang/AST/Type.h"
20#include "clang/Basic/SourceLocation.h"
21#include "clang/Sema/Lookup.h"
22#include "clang/Sema/Sema.h"
23#include "clang/Sema/SemaHLSL.h"
24#include "llvm/ADT/SmallVector.h"
25
26using namespace clang;
27using namespace llvm::hlsl;
28
29using clang::hlsl::BuiltinTypeDeclBuilder;
30
31void HLSLExternalSemaSource::InitializeSema(Sema &S) {
32 SemaPtr = &S;
33 ASTContext &AST = SemaPtr->getASTContext();
34 // If the translation unit has external storage force external decls to load.
35 if (AST.getTranslationUnitDecl()->hasExternalLexicalStorage())
36 (void)AST.getTranslationUnitDecl()->decls_begin();
37
38 IdentifierInfo &HLSL = AST.Idents.get(Name: "hlsl", TokenCode: tok::TokenKind::identifier);
39 LookupResult Result(S, &HLSL, SourceLocation(), Sema::LookupNamespaceName);
40 NamespaceDecl *PrevDecl = nullptr;
41 if (S.LookupQualifiedName(R&: Result, LookupCtx: AST.getTranslationUnitDecl()))
42 PrevDecl = Result.getAsSingle<NamespaceDecl>();
43 HLSLNamespace = NamespaceDecl::Create(
44 C&: AST, DC: AST.getTranslationUnitDecl(), /*Inline=*/false, StartLoc: SourceLocation(),
45 IdLoc: SourceLocation(), Id: &HLSL, PrevDecl, /*Nested=*/false);
46 HLSLNamespace->setImplicit(true);
47 HLSLNamespace->setHasExternalLexicalStorage();
48 AST.getTranslationUnitDecl()->addDecl(D: HLSLNamespace);
49
50 // Force external decls in the HLSL namespace to load from the PCH.
51 (void)HLSLNamespace->getCanonicalDecl()->decls_begin();
52 defineTrivialHLSLTypes();
53 defineHLSLTypesWithForwardDeclarations();
54
55 // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's
56 // built in types inside a namespace, but we are planning to change that in
57 // the near future. In order to be source compatible older versions of HLSL
58 // will need to implicitly use the hlsl namespace. For now in clang everything
59 // will get added to the namespace, and we can remove the using directive for
60 // future language versions to match HLSL's evolution.
61 auto *UsingDecl = UsingDirectiveDecl::Create(
62 C&: AST, DC: AST.getTranslationUnitDecl(), UsingLoc: SourceLocation(), NamespaceLoc: SourceLocation(),
63 QualifierLoc: NestedNameSpecifierLoc(), IdentLoc: SourceLocation(), Nominated: HLSLNamespace,
64 CommonAncestor: AST.getTranslationUnitDecl());
65
66 AST.getTranslationUnitDecl()->addDecl(D: UsingDecl);
67}
68
69void HLSLExternalSemaSource::defineHLSLVectorAlias() {
70 ASTContext &AST = SemaPtr->getASTContext();
71
72 llvm::SmallVector<NamedDecl *> TemplateParams;
73
74 auto *TypeParam = TemplateTypeParmDecl::Create(
75 C: AST, DC: HLSLNamespace, KeyLoc: SourceLocation(), NameLoc: SourceLocation(), D: 0, P: 0,
76 Id: &AST.Idents.get(Name: "element", TokenCode: tok::TokenKind::identifier), Typename: false, ParameterPack: false);
77 TypeParam->setDefaultArgument(
78 C: AST, DefArg: SemaPtr->getTrivialTemplateArgumentLoc(
79 Arg: TemplateArgument(AST.FloatTy), NTTPType: QualType(), Loc: SourceLocation()));
80
81 TemplateParams.emplace_back(Args&: TypeParam);
82
83 auto *SizeParam = NonTypeTemplateParmDecl::Create(
84 C: AST, DC: HLSLNamespace, StartLoc: SourceLocation(), IdLoc: SourceLocation(), D: 0, P: 1,
85 Id: &AST.Idents.get(Name: "element_count", TokenCode: tok::TokenKind::identifier), T: AST.IntTy,
86 ParameterPack: false, TInfo: AST.getTrivialTypeSourceInfo(T: AST.IntTy));
87 llvm::APInt Val(AST.getIntWidth(T: AST.IntTy), 4);
88 TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy,
89 /*IsDefaulted=*/true);
90 SizeParam->setDefaultArgument(
91 C: AST, DefArg: SemaPtr->getTrivialTemplateArgumentLoc(Arg: Default, NTTPType: AST.IntTy,
92 Loc: SourceLocation(), TemplateParam: SizeParam));
93 TemplateParams.emplace_back(Args&: SizeParam);
94
95 auto *ParamList =
96 TemplateParameterList::Create(C: AST, TemplateLoc: SourceLocation(), LAngleLoc: SourceLocation(),
97 Params: TemplateParams, RAngleLoc: SourceLocation(), RequiresClause: nullptr);
98
99 IdentifierInfo &II = AST.Idents.get(Name: "vector", TokenCode: tok::TokenKind::identifier);
100
101 QualType AliasType = AST.getDependentSizedExtVectorType(
102 VectorType: AST.getTemplateTypeParmType(Depth: 0, Index: 0, ParameterPack: false, ParmDecl: TypeParam),
103 SizeExpr: DeclRefExpr::Create(
104 Context: AST, QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: SizeParam, RefersToEnclosingVariableOrCapture: false,
105 NameInfo: DeclarationNameInfo(SizeParam->getDeclName(), SourceLocation()),
106 T: AST.IntTy, VK: VK_LValue),
107 AttrLoc: SourceLocation());
108
109 auto *Record = TypeAliasDecl::Create(C&: AST, DC: HLSLNamespace, StartLoc: SourceLocation(),
110 IdLoc: SourceLocation(), Id: &II,
111 TInfo: AST.getTrivialTypeSourceInfo(T: AliasType));
112 Record->setImplicit(true);
113
114 auto *Template =
115 TypeAliasTemplateDecl::Create(C&: AST, DC: HLSLNamespace, L: SourceLocation(),
116 Name: Record->getIdentifier(), Params: ParamList, Decl: Record);
117
118 Record->setDescribedAliasTemplate(Template);
119 Template->setImplicit(true);
120 Template->setLexicalDeclContext(Record->getDeclContext());
121 HLSLNamespace->addDecl(D: Template);
122}
123
124void HLSLExternalSemaSource::defineHLSLMatrixAlias() {
125 ASTContext &AST = SemaPtr->getASTContext();
126 llvm::SmallVector<NamedDecl *> TemplateParams;
127
128 auto *TypeParam = TemplateTypeParmDecl::Create(
129 C: AST, DC: HLSLNamespace, KeyLoc: SourceLocation(), NameLoc: SourceLocation(), D: 0, P: 0,
130 Id: &AST.Idents.get(Name: "element", TokenCode: tok::TokenKind::identifier), Typename: false, ParameterPack: false);
131 TypeParam->setDefaultArgument(
132 C: AST, DefArg: SemaPtr->getTrivialTemplateArgumentLoc(
133 Arg: TemplateArgument(AST.FloatTy), NTTPType: QualType(), Loc: SourceLocation()));
134
135 TemplateParams.emplace_back(Args&: TypeParam);
136
137 // these should be 64 bit to be consistent with other clang matrices.
138 auto *RowsParam = NonTypeTemplateParmDecl::Create(
139 C: AST, DC: HLSLNamespace, StartLoc: SourceLocation(), IdLoc: SourceLocation(), D: 0, P: 1,
140 Id: &AST.Idents.get(Name: "rows_count", TokenCode: tok::TokenKind::identifier), T: AST.IntTy,
141 ParameterPack: false, TInfo: AST.getTrivialTypeSourceInfo(T: AST.IntTy));
142 llvm::APInt RVal(AST.getIntWidth(T: AST.IntTy), 4);
143 TemplateArgument RDefault(AST, llvm::APSInt(std::move(RVal)), AST.IntTy,
144 /*IsDefaulted=*/true);
145 RowsParam->setDefaultArgument(
146 C: AST, DefArg: SemaPtr->getTrivialTemplateArgumentLoc(Arg: RDefault, NTTPType: AST.IntTy,
147 Loc: SourceLocation(), TemplateParam: RowsParam));
148 TemplateParams.emplace_back(Args&: RowsParam);
149
150 auto *ColsParam = NonTypeTemplateParmDecl::Create(
151 C: AST, DC: HLSLNamespace, StartLoc: SourceLocation(), IdLoc: SourceLocation(), D: 0, P: 2,
152 Id: &AST.Idents.get(Name: "cols_count", TokenCode: tok::TokenKind::identifier), T: AST.IntTy,
153 ParameterPack: false, TInfo: AST.getTrivialTypeSourceInfo(T: AST.IntTy));
154 llvm::APInt CVal(AST.getIntWidth(T: AST.IntTy), 4);
155 TemplateArgument CDefault(AST, llvm::APSInt(std::move(CVal)), AST.IntTy,
156 /*IsDefaulted=*/true);
157 ColsParam->setDefaultArgument(
158 C: AST, DefArg: SemaPtr->getTrivialTemplateArgumentLoc(Arg: CDefault, NTTPType: AST.IntTy,
159 Loc: SourceLocation(), TemplateParam: ColsParam));
160 TemplateParams.emplace_back(Args&: ColsParam);
161
162 const unsigned MaxMatDim = SemaPtr->getLangOpts().MaxMatrixDimension;
163
164 auto *MaxRow = IntegerLiteral::Create(
165 C: AST, V: llvm::APInt(AST.getIntWidth(T: AST.IntTy), MaxMatDim), type: AST.IntTy,
166 l: SourceLocation());
167 auto *MaxCol = IntegerLiteral::Create(
168 C: AST, V: llvm::APInt(AST.getIntWidth(T: AST.IntTy), MaxMatDim), type: AST.IntTy,
169 l: SourceLocation());
170
171 auto *RowsRef = DeclRefExpr::Create(
172 Context: AST, QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: RowsParam,
173 /*RefersToEnclosingVariableOrCapture*/ false,
174 NameInfo: DeclarationNameInfo(RowsParam->getDeclName(), SourceLocation()),
175 T: AST.IntTy, VK: VK_LValue);
176 auto *ColsRef = DeclRefExpr::Create(
177 Context: AST, QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: ColsParam,
178 /*RefersToEnclosingVariableOrCapture*/ false,
179 NameInfo: DeclarationNameInfo(ColsParam->getDeclName(), SourceLocation()),
180 T: AST.IntTy, VK: VK_LValue);
181
182 auto *RowsLE = BinaryOperator::Create(C: AST, lhs: RowsRef, rhs: MaxRow, opc: BO_LE, ResTy: AST.BoolTy,
183 VK: VK_PRValue, OK: OK_Ordinary,
184 opLoc: SourceLocation(), FPFeatures: FPOptionsOverride());
185 auto *ColsLE = BinaryOperator::Create(C: AST, lhs: ColsRef, rhs: MaxCol, opc: BO_LE, ResTy: AST.BoolTy,
186 VK: VK_PRValue, OK: OK_Ordinary,
187 opLoc: SourceLocation(), FPFeatures: FPOptionsOverride());
188
189 auto *RequiresExpr = BinaryOperator::Create(
190 C: AST, lhs: RowsLE, rhs: ColsLE, opc: BO_LAnd, ResTy: AST.BoolTy, VK: VK_PRValue, OK: OK_Ordinary,
191 opLoc: SourceLocation(), FPFeatures: FPOptionsOverride());
192
193 auto *ParamList = TemplateParameterList::Create(
194 C: AST, TemplateLoc: SourceLocation(), LAngleLoc: SourceLocation(), Params: TemplateParams, RAngleLoc: SourceLocation(),
195 RequiresClause: RequiresExpr);
196
197 IdentifierInfo &II = AST.Idents.get(Name: "matrix", TokenCode: tok::TokenKind::identifier);
198
199 QualType AliasType = AST.getDependentSizedMatrixType(
200 ElementType: AST.getTemplateTypeParmType(Depth: 0, Index: 0, ParameterPack: false, ParmDecl: TypeParam),
201 RowExpr: DeclRefExpr::Create(
202 Context: AST, QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: RowsParam, RefersToEnclosingVariableOrCapture: false,
203 NameInfo: DeclarationNameInfo(RowsParam->getDeclName(), SourceLocation()),
204 T: AST.IntTy, VK: VK_LValue),
205 ColumnExpr: DeclRefExpr::Create(
206 Context: AST, QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: ColsParam, RefersToEnclosingVariableOrCapture: false,
207 NameInfo: DeclarationNameInfo(ColsParam->getDeclName(), SourceLocation()),
208 T: AST.IntTy, VK: VK_LValue),
209 AttrLoc: SourceLocation());
210
211 auto *Record = TypeAliasDecl::Create(C&: AST, DC: HLSLNamespace, StartLoc: SourceLocation(),
212 IdLoc: SourceLocation(), Id: &II,
213 TInfo: AST.getTrivialTypeSourceInfo(T: AliasType));
214 Record->setImplicit(true);
215
216 auto *Template =
217 TypeAliasTemplateDecl::Create(C&: AST, DC: HLSLNamespace, L: SourceLocation(),
218 Name: Record->getIdentifier(), Params: ParamList, Decl: Record);
219
220 Record->setDescribedAliasTemplate(Template);
221 Template->setImplicit(true);
222 Template->setLexicalDeclContext(Record->getDeclContext());
223 HLSLNamespace->addDecl(D: Template);
224}
225
226void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
227 defineHLSLVectorAlias();
228 defineHLSLMatrixAlias();
229}
230
231/// Set up common members and attributes for buffer types
232static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
233 ResourceClass RC, bool IsROV,
234 bool RawBuffer, bool HasCounter) {
235 return BuiltinTypeDeclBuilder(S, Decl)
236 .addBufferHandles(RC, IsROV, RawBuffer, HasCounter)
237 .addDefaultHandleConstructor()
238 .addCopyConstructor()
239 .addCopyAssignmentOperator()
240 .addStaticInitializationFunctions(HasCounter);
241}
242
243/// Set up common members and attributes for sampler types
244static BuiltinTypeDeclBuilder setupSamplerType(CXXRecordDecl *Decl, Sema &S) {
245 return BuiltinTypeDeclBuilder(S, Decl)
246 .addSamplerHandle()
247 .addDefaultHandleConstructor()
248 .addCopyConstructor()
249 .addCopyAssignmentOperator()
250 .addStaticInitializationFunctions(HasCounter: false);
251}
252
253/// Set up common members and attributes for texture types
254static BuiltinTypeDeclBuilder setupTextureType(CXXRecordDecl *Decl, Sema &S,
255 ResourceClass RC, bool IsROV,
256 ResourceDimension Dim) {
257 return BuiltinTypeDeclBuilder(S, Decl)
258 .addTextureHandle(RC, IsROV, RD: Dim)
259 .addDefaultHandleConstructor()
260 .addCopyConstructor()
261 .addCopyAssignmentOperator()
262 .addStaticInitializationFunctions(HasCounter: false)
263 .addSampleMethods(Dim);
264}
265
266// This function is responsible for constructing the constraint expression for
267// this concept:
268// template<typename T> concept is_typed_resource_element_compatible =
269// __is_typed_resource_element_compatible<T>;
270static Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
271 TemplateTypeParmDecl *T) {
272 ASTContext &Context = S.getASTContext();
273
274 // Obtain the QualType for 'bool'
275 QualType BoolTy = Context.BoolTy;
276
277 // Create a QualType that points to this TemplateTypeParmDecl
278 QualType TType = Context.getTypeDeclType(Decl: T);
279
280 // Create a TypeSourceInfo for the template type parameter 'T'
281 TypeSourceInfo *TTypeSourceInfo =
282 Context.getTrivialTypeSourceInfo(T: TType, Loc: NameLoc);
283
284 TypeTraitExpr *TypedResExpr = TypeTraitExpr::Create(
285 C: Context, T: BoolTy, Loc: NameLoc, Kind: UTT_IsTypedResourceElementCompatible,
286 Args: {TTypeSourceInfo}, RParenLoc: NameLoc, Value: true);
287
288 return TypedResExpr;
289}
290
291// This function is responsible for constructing the constraint expression for
292// this concept:
293// template<typename T> concept is_structured_resource_element_compatible =
294// !__is_intangible<T> && sizeof(T) >= 1;
295static Expr *constructStructuredBufferConstraintExpr(Sema &S,
296 SourceLocation NameLoc,
297 TemplateTypeParmDecl *T) {
298 ASTContext &Context = S.getASTContext();
299
300 // Obtain the QualType for 'bool'
301 QualType BoolTy = Context.BoolTy;
302
303 // Create a QualType that points to this TemplateTypeParmDecl
304 QualType TType = Context.getTypeDeclType(Decl: T);
305
306 // Create a TypeSourceInfo for the template type parameter 'T'
307 TypeSourceInfo *TTypeSourceInfo =
308 Context.getTrivialTypeSourceInfo(T: TType, Loc: NameLoc);
309
310 TypeTraitExpr *IsIntangibleExpr =
311 TypeTraitExpr::Create(C: Context, T: BoolTy, Loc: NameLoc, Kind: UTT_IsIntangibleType,
312 Args: {TTypeSourceInfo}, RParenLoc: NameLoc, Value: true);
313
314 // negate IsIntangibleExpr
315 UnaryOperator *NotIntangibleExpr = UnaryOperator::Create(
316 C: Context, input: IsIntangibleExpr, opc: UO_LNot, type: BoolTy, VK: VK_LValue, OK: OK_Ordinary,
317 l: NameLoc, CanOverflow: false, FPFeatures: FPOptionsOverride());
318
319 // element types also may not be of 0 size
320 UnaryExprOrTypeTraitExpr *SizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
321 UETT_SizeOf, TTypeSourceInfo, BoolTy, NameLoc, NameLoc);
322
323 // Create a BinaryOperator that checks if the size of the type is not equal to
324 // 1 Empty structs have a size of 1 in HLSL, so we need to check for that
325 IntegerLiteral *rhs = IntegerLiteral::Create(
326 C: Context, V: llvm::APInt(Context.getTypeSize(T: Context.getSizeType()), 1, true),
327 type: Context.getSizeType(), l: NameLoc);
328
329 BinaryOperator *SizeGEQOneExpr =
330 BinaryOperator::Create(C: Context, lhs: SizeOfExpr, rhs, opc: BO_GE, ResTy: BoolTy, VK: VK_LValue,
331 OK: OK_Ordinary, opLoc: NameLoc, FPFeatures: FPOptionsOverride());
332
333 // Combine the two constraints
334 BinaryOperator *CombinedExpr = BinaryOperator::Create(
335 C: Context, lhs: NotIntangibleExpr, rhs: SizeGEQOneExpr, opc: BO_LAnd, ResTy: BoolTy, VK: VK_LValue,
336 OK: OK_Ordinary, opLoc: NameLoc, FPFeatures: FPOptionsOverride());
337
338 return CombinedExpr;
339}
340
341static ConceptDecl *constructBufferConceptDecl(Sema &S, NamespaceDecl *NSD,
342 bool isTypedBuffer) {
343 ASTContext &Context = S.getASTContext();
344 DeclContext *DC = NSD->getDeclContext();
345 SourceLocation DeclLoc = SourceLocation();
346
347 IdentifierInfo &ElementTypeII = Context.Idents.get(Name: "element_type");
348 TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
349 C: Context, DC: NSD->getDeclContext(), KeyLoc: DeclLoc, NameLoc: DeclLoc,
350 /*D=*/0,
351 /*P=*/0,
352 /*Id=*/&ElementTypeII,
353 /*Typename=*/true,
354 /*ParameterPack=*/false);
355
356 T->setDeclContext(DC);
357 T->setReferenced();
358
359 // Create and Attach Template Parameter List to ConceptDecl
360 TemplateParameterList *ConceptParams = TemplateParameterList::Create(
361 C: Context, TemplateLoc: DeclLoc, LAngleLoc: DeclLoc, Params: {T}, RAngleLoc: DeclLoc, RequiresClause: nullptr);
362
363 DeclarationName DeclName;
364 Expr *ConstraintExpr = nullptr;
365
366 if (isTypedBuffer) {
367 DeclName = DeclarationName(
368 &Context.Idents.get(Name: "__is_typed_resource_element_compatible"));
369 ConstraintExpr = constructTypedBufferConstraintExpr(S, NameLoc: DeclLoc, T);
370 } else {
371 DeclName = DeclarationName(
372 &Context.Idents.get(Name: "__is_structured_resource_element_compatible"));
373 ConstraintExpr = constructStructuredBufferConstraintExpr(S, NameLoc: DeclLoc, T);
374 }
375
376 // Create a ConceptDecl
377 ConceptDecl *CD =
378 ConceptDecl::Create(C&: Context, DC: NSD->getDeclContext(), L: DeclLoc, Name: DeclName,
379 Params: ConceptParams, ConstraintExpr);
380
381 // Attach the template parameter list to the ConceptDecl
382 CD->setTemplateParameters(ConceptParams);
383
384 // Add the concept declaration to the Translation Unit Decl
385 NSD->getDeclContext()->addDecl(D: CD);
386
387 return CD;
388}
389
390void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
391 CXXRecordDecl *Decl;
392 ConceptDecl *TypedBufferConcept = constructBufferConceptDecl(
393 S&: *SemaPtr, NSD: HLSLNamespace, /*isTypedBuffer*/ true);
394 ConceptDecl *StructuredBufferConcept = constructBufferConceptDecl(
395 S&: *SemaPtr, NSD: HLSLNamespace, /*isTypedBuffer*/ false);
396
397 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "Buffer")
398 .addSimpleTemplateParams(Names: {"element_type"}, CD: TypedBufferConcept)
399 .finalizeForwardDeclaration();
400
401 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
402 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::SRV, /*IsROV=*/false,
403 /*RawBuffer=*/false, /*HasCounter=*/false)
404 .addArraySubscriptOperators()
405 .addLoadMethods()
406 .addGetDimensionsMethodForBuffer()
407 .completeDefinition();
408 });
409
410 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
411 .addSimpleTemplateParams(Names: {"element_type"}, CD: TypedBufferConcept)
412 .finalizeForwardDeclaration();
413
414 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
415 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::UAV, /*IsROV=*/false,
416 /*RawBuffer=*/false, /*HasCounter=*/false)
417 .addArraySubscriptOperators()
418 .addLoadMethods()
419 .addGetDimensionsMethodForBuffer()
420 .completeDefinition();
421 });
422
423 Decl =
424 BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer")
425 .addSimpleTemplateParams(Names: {"element_type"}, CD: StructuredBufferConcept)
426 .finalizeForwardDeclaration();
427 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
428 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::UAV, /*IsROV=*/true,
429 /*RawBuffer=*/false, /*HasCounter=*/false)
430 .addArraySubscriptOperators()
431 .addLoadMethods()
432 .addGetDimensionsMethodForBuffer()
433 .completeDefinition();
434 });
435
436 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer")
437 .addSimpleTemplateParams(Names: {"element_type"}, CD: StructuredBufferConcept)
438 .finalizeForwardDeclaration();
439 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
440 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::SRV, /*IsROV=*/false,
441 /*RawBuffer=*/true, /*HasCounter=*/false)
442 .addArraySubscriptOperators()
443 .addLoadMethods()
444 .addGetDimensionsMethodForBuffer()
445 .completeDefinition();
446 });
447
448 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWStructuredBuffer")
449 .addSimpleTemplateParams(Names: {"element_type"}, CD: StructuredBufferConcept)
450 .finalizeForwardDeclaration();
451 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
452 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::UAV, /*IsROV=*/false,
453 /*RawBuffer=*/true, /*HasCounter=*/true)
454 .addArraySubscriptOperators()
455 .addLoadMethods()
456 .addIncrementCounterMethod()
457 .addDecrementCounterMethod()
458 .addGetDimensionsMethodForBuffer()
459 .completeDefinition();
460 });
461
462 Decl =
463 BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "AppendStructuredBuffer")
464 .addSimpleTemplateParams(Names: {"element_type"}, CD: StructuredBufferConcept)
465 .finalizeForwardDeclaration();
466 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
467 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::UAV, /*IsROV=*/false,
468 /*RawBuffer=*/true, /*HasCounter=*/true)
469 .addAppendMethod()
470 .addGetDimensionsMethodForBuffer()
471 .completeDefinition();
472 });
473
474 Decl =
475 BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConsumeStructuredBuffer")
476 .addSimpleTemplateParams(Names: {"element_type"}, CD: StructuredBufferConcept)
477 .finalizeForwardDeclaration();
478 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
479 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::UAV, /*IsROV=*/false,
480 /*RawBuffer=*/true, /*HasCounter=*/true)
481 .addConsumeMethod()
482 .addGetDimensionsMethodForBuffer()
483 .completeDefinition();
484 });
485
486 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
487 "RasterizerOrderedStructuredBuffer")
488 .addSimpleTemplateParams(Names: {"element_type"}, CD: StructuredBufferConcept)
489 .finalizeForwardDeclaration();
490 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
491 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::UAV, /*IsROV=*/true,
492 /*RawBuffer=*/true, /*HasCounter=*/true)
493 .addArraySubscriptOperators()
494 .addLoadMethods()
495 .addIncrementCounterMethod()
496 .addDecrementCounterMethod()
497 .addGetDimensionsMethodForBuffer()
498 .completeDefinition();
499 });
500
501 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ByteAddressBuffer")
502 .finalizeForwardDeclaration();
503 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
504 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::SRV, /*IsROV=*/false,
505 /*RawBuffer=*/true, /*HasCounter=*/false)
506 .addGetDimensionsMethodForBuffer()
507 .completeDefinition();
508 });
509 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWByteAddressBuffer")
510 .finalizeForwardDeclaration();
511 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
512 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::UAV, /*IsROV=*/false,
513 /*RawBuffer=*/true, /*HasCounter=*/false)
514 .addGetDimensionsMethodForBuffer()
515 .completeDefinition();
516 });
517 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
518 "RasterizerOrderedByteAddressBuffer")
519 .finalizeForwardDeclaration();
520 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
521 setupBufferType(Decl, S&: *SemaPtr, RC: ResourceClass::UAV, /*IsROV=*/true,
522 /*RawBuffer=*/true, /*HasCounter=*/false)
523 .addGetDimensionsMethodForBuffer()
524 .completeDefinition();
525 });
526
527 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "SamplerState")
528 .finalizeForwardDeclaration();
529 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
530 setupSamplerType(Decl, S&: *SemaPtr).completeDefinition();
531 });
532
533 Decl =
534 BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "SamplerComparisonState")
535 .finalizeForwardDeclaration();
536 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
537 setupSamplerType(Decl, S&: *SemaPtr).completeDefinition();
538 });
539
540 Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "Texture2D")
541 .addSimpleTemplateParams(Names: {"element_type"}, CD: TypedBufferConcept)
542 .finalizeForwardDeclaration();
543 onCompletion(Record: Decl, Fn: [this](CXXRecordDecl *Decl) {
544 setupTextureType(Decl, S&: *SemaPtr, RC: ResourceClass::SRV, /*IsROV=*/false,
545 Dim: ResourceDimension::Dim2D)
546 .completeDefinition();
547 });
548}
549
550void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
551 CompletionFunction Fn) {
552 if (!Record->isCompleteDefinition())
553 Completions.insert(KV: std::make_pair(x: Record->getCanonicalDecl(), y&: Fn));
554}
555
556void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) {
557 if (!isa<CXXRecordDecl>(Val: Tag))
558 return;
559 auto Record = cast<CXXRecordDecl>(Val: Tag);
560
561 // If this is a specialization, we need to get the underlying templated
562 // declaration and complete that.
563 if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Val: Record))
564 Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
565 Record = Record->getCanonicalDecl();
566 auto It = Completions.find(Val: Record);
567 if (It == Completions.end())
568 return;
569 It->second(Record);
570 Completions.erase(I: It);
571}
572