15
15
#include " clang/AST/Decl.h"
16
16
#include " clang/AST/DeclBase.h"
17
17
#include " clang/AST/DeclCXX.h"
18
+ #include " clang/AST/DeclarationName.h"
18
19
#include " clang/AST/DynamicRecursiveASTVisitor.h"
19
20
#include " clang/AST/Expr.h"
20
21
#include " clang/AST/Type.h"
46
47
using namespace clang ;
47
48
using RegisterType = HLSLResourceBindingAttr::RegisterType;
48
49
49
- static CXXRecordDecl *createHostLayoutStruct (Sema &S, CXXRecordDecl *StructDecl,
50
- HLSLBufferDecl *BufDecl );
50
+ static CXXRecordDecl *createHostLayoutStruct (Sema &S,
51
+ CXXRecordDecl *StructDecl );
51
52
52
53
static RegisterType getRegisterType (ResourceClass RC) {
53
54
switch (RC) {
@@ -268,6 +269,30 @@ static bool isZeroSizedArray(const ConstantArrayType *CAT) {
268
269
return CAT != nullptr ;
269
270
}
270
271
272
+ // Returns true if the record type is an HLSL resource class
273
+ static bool isResourceRecordType (const Type *Ty) {
274
+ return HLSLAttributedResourceType::findHandleTypeOnResource (Ty) != nullptr ;
275
+ }
276
+
277
+ // Returns true if the type is a leaf element type that is not valid to be included
278
+ // in HLSL Buffer, such as a resource class, empty struct, zero-sized array,
279
+ // or a builtin intangible type.
280
+ // Returns false it is a valid leaf element type or if it is a record type that
281
+ // needs to be inspected further.
282
+ static bool isInvalidConstantBufferLeafElementType (const Type *Ty) {
283
+ if (Ty->isRecordType ()) {
284
+ if (isResourceRecordType (Ty) || Ty->getAsCXXRecordDecl ()->isEmpty ())
285
+ return true ;
286
+ return false ;
287
+ }
288
+ if (Ty->isConstantArrayType () &&
289
+ isZeroSizedArray (cast<ConstantArrayType>(Ty)))
290
+ return true ;
291
+ if (Ty->isHLSLBuiltinIntangibleType ())
292
+ return true ;
293
+ return false ;
294
+ }
295
+
271
296
// Returns true if the struct contains at least one element that prevents it
272
297
// from being included inside HLSL Buffer as is, such as an intangible type,
273
298
// empty struct, or zero-sized array. If it does, a new implicit layout struct
@@ -279,13 +304,11 @@ static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD) {
279
304
// check fields
280
305
for (const FieldDecl *Field : RD->fields ()) {
281
306
QualType Ty = Field->getType ();
282
- if (Ty->isRecordType ()) {
283
- if (requiresImplicitBufferLayoutStructure (Ty->getAsCXXRecordDecl ()))
284
- return true ;
285
- } else if (Ty->isConstantArrayType ()) {
286
- if (isZeroSizedArray (cast<ConstantArrayType>(Ty)))
287
- return true ;
288
- }
307
+ if (isInvalidConstantBufferLeafElementType (Ty.getTypePtr ()))
308
+ return true ;
309
+ if (Ty->isRecordType () &&
310
+ requiresImplicitBufferLayoutStructure (Ty->getAsCXXRecordDecl ()))
311
+ return true ;
289
312
}
290
313
// check bases
291
314
for (const CXXBaseSpecifier &Base : RD->bases ())
@@ -295,25 +318,28 @@ static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD) {
295
318
return false ;
296
319
}
297
320
298
- static CXXRecordDecl *findRecordDecl (Sema &S, IdentifierInfo *II,
299
- DeclContext *DC) {
300
- DeclarationNameInfo NameInfo =
301
- DeclarationNameInfo (DeclarationName (II), SourceLocation ());
302
- LookupResult R (S, NameInfo, Sema::LookupTagName);
303
- S.LookupName (R, S.getScopeForContext (DC));
304
- if (R.isSingleResult ())
305
- return R.getAsSingle <CXXRecordDecl>();
306
- return nullptr ;
321
+ static CXXRecordDecl *findRecordDeclInContext (IdentifierInfo *II,
322
+ DeclContext *DC) {
323
+ CXXRecordDecl *RD = nullptr ;
324
+ for (NamedDecl *Decl :
325
+ DC->getNonTransparentContext ()->lookup (DeclarationName (II))) {
326
+ if (CXXRecordDecl *FoundRD = dyn_cast<CXXRecordDecl>(Decl)) {
327
+ assert (RD == nullptr &&
328
+ " there should be at most 1 record by a given name in a scope" );
329
+ RD = FoundRD;
330
+ }
331
+ }
332
+ return RD;
307
333
}
308
334
309
335
// Creates a name for buffer layout struct using the provide name base.
310
336
// If the name must be unique (not previously defined), a suffix is added
311
337
// until a unique name is found.
312
- static IdentifierInfo *getHostLayoutStructName (Sema &S,
313
- IdentifierInfo *NameBaseII,
314
- bool MustBeUnique,
315
- DeclContext *DC) {
338
+ static IdentifierInfo *getHostLayoutStructName (Sema &S, NamedDecl *BaseDecl,
339
+ bool MustBeUnique) {
316
340
ASTContext &AST = S.getASTContext ();
341
+
342
+ IdentifierInfo *NameBaseII = BaseDecl->getIdentifier ();
317
343
StringRef NameBase;
318
344
if (NameBaseII) {
319
345
NameBase = NameBaseII->getName ();
@@ -333,39 +359,31 @@ static IdentifierInfo *getHostLayoutStructName(Sema &S,
333
359
if (suffix != 0 )
334
360
II = &AST.Idents .get ((Name + " _" + Twine (suffix)).str (),
335
361
tok::TokenKind::identifier);
336
- if (!findRecordDecl (S, II, DC ))
362
+ if (!findRecordDeclInContext ( II, BaseDecl-> getDeclContext () ))
337
363
return II;
338
364
// declaration with that name already exists - increment suffix and try
339
365
// again until unique name is found
340
366
suffix++;
341
367
};
342
368
}
343
369
344
- // Returns true if the record type is an HLSL resource class
345
- static bool isResourceRecordType (const Type *Ty) {
346
- return HLSLAttributedResourceType::findHandleTypeOnResource (Ty) != nullptr ;
347
- }
348
-
349
370
// Creates a field declaration of given name and type for HLSL buffer layout
350
371
// struct. Returns nullptr if the type cannot be use in HLSL Buffer layout.
351
372
static FieldDecl *createFieldForHostLayoutStruct (Sema &S, const Type *Ty,
352
373
IdentifierInfo *II,
353
- CXXRecordDecl *LayoutStruct,
354
- HLSLBufferDecl *BufDecl) {
374
+ CXXRecordDecl *LayoutStruct) {
375
+ if (isInvalidConstantBufferLeafElementType (Ty))
376
+ return nullptr ;
377
+
355
378
if (Ty->isRecordType ()) {
356
- if (isResourceRecordType (Ty))
357
- return nullptr ;
358
379
CXXRecordDecl *RD = Ty->getAsCXXRecordDecl ();
359
380
if (requiresImplicitBufferLayoutStructure (RD)) {
360
- RD = createHostLayoutStruct (S, RD, BufDecl );
381
+ RD = createHostLayoutStruct (S, RD);
361
382
if (!RD)
362
383
return nullptr ;
363
384
Ty = RD->getTypeForDecl ();
364
385
}
365
386
}
366
- if (Ty->isConstantArrayType () &&
367
- isZeroSizedArray (cast<ConstantArrayType>(Ty)))
368
- return nullptr ;
369
387
370
388
QualType QT = QualType (Ty, 0 );
371
389
ASTContext &AST = S.getASTContext ();
@@ -384,23 +402,21 @@ static FieldDecl *createFieldForHostLayoutStruct(Sema &S, const Type *Ty,
384
402
// - empty structs
385
403
// - zero-sized arrays
386
404
// Returns nullptr if the resulting layout struct would be empty.
387
- static CXXRecordDecl *createHostLayoutStruct (Sema &S, CXXRecordDecl *StructDecl,
388
- HLSLBufferDecl *BufDecl ) {
405
+ static CXXRecordDecl *createHostLayoutStruct (Sema &S,
406
+ CXXRecordDecl *StructDecl ) {
389
407
assert (requiresImplicitBufferLayoutStructure (StructDecl) &&
390
408
" struct is already HLSL buffer compatible" );
391
409
392
410
ASTContext &AST = S.getASTContext ();
393
411
DeclContext *DC = StructDecl->getDeclContext ();
394
- IdentifierInfo *II = getHostLayoutStructName (
395
- S, StructDecl->getIdentifier (), false , BufDecl->getDeclContext ());
412
+ IdentifierInfo *II = getHostLayoutStructName (S, StructDecl, false );
396
413
397
414
// reuse existing if the layout struct if it already exists
398
- if (CXXRecordDecl *RD = findRecordDecl (S, II, DC))
415
+ if (CXXRecordDecl *RD = findRecordDeclInContext ( II, DC))
399
416
return RD;
400
417
401
- CXXRecordDecl *LS =
402
- CXXRecordDecl::Create (AST, TagDecl::TagKind::Class, BufDecl,
403
- SourceLocation (), SourceLocation (), II);
418
+ CXXRecordDecl *LS = CXXRecordDecl::Create (
419
+ AST, TagDecl::TagKind::Class, DC, SourceLocation (), SourceLocation (), II);
404
420
LS->setImplicit (true );
405
421
LS->startDefinition ();
406
422
@@ -410,7 +426,7 @@ static CXXRecordDecl *createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl,
410
426
CXXBaseSpecifier Base = *StructDecl->bases_begin ();
411
427
CXXRecordDecl *BaseDecl = Base.getType ()->getAsCXXRecordDecl ();
412
428
if (requiresImplicitBufferLayoutStructure (BaseDecl)) {
413
- BaseDecl = createHostLayoutStruct (S, BaseDecl, BufDecl );
429
+ BaseDecl = createHostLayoutStruct (S, BaseDecl);
414
430
if (BaseDecl) {
415
431
TypeSourceInfo *TSI = AST.getTrivialTypeSourceInfo (
416
432
QualType (BaseDecl->getTypeForDecl (), 0 ));
@@ -427,15 +443,16 @@ static CXXRecordDecl *createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl,
427
443
// filter struct fields
428
444
for (const FieldDecl *FD : StructDecl->fields ()) {
429
445
const Type *Ty = FD->getType ()->getUnqualifiedDesugaredType ();
430
- if (FieldDecl *NewFD = createFieldForHostLayoutStruct (
431
- S, Ty, FD->getIdentifier (), LS, BufDecl ))
446
+ if (FieldDecl *NewFD =
447
+ createFieldForHostLayoutStruct ( S, Ty, FD->getIdentifier (), LS))
432
448
LS->addDecl (NewFD);
433
449
}
434
450
LS->completeDefinition ();
435
451
436
452
if (LS->field_empty () && LS->getNumBases () == 0 )
437
453
return nullptr ;
438
- BufDecl->addDecl (LS);
454
+
455
+ DC->addDecl (LS);
439
456
return LS;
440
457
}
441
458
@@ -449,8 +466,7 @@ static CXXRecordDecl *createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl,
449
466
// The layour struct will be added to the HLSLBufferDecl declarations.
450
467
void createHostLayoutStructForBuffer (Sema &S, HLSLBufferDecl *BufDecl) {
451
468
ASTContext &AST = S.getASTContext ();
452
- IdentifierInfo *II = getHostLayoutStructName (S, BufDecl->getIdentifier (),
453
- true , BufDecl->getDeclContext ());
469
+ IdentifierInfo *II = getHostLayoutStructName (S, BufDecl, true );
454
470
455
471
CXXRecordDecl *LS =
456
472
CXXRecordDecl::Create (AST, TagDecl::TagKind::Class, BufDecl,
@@ -463,8 +479,8 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {
463
479
if (!VD || VD->getStorageClass () == SC_Static)
464
480
continue ;
465
481
const Type *Ty = VD->getType ()->getUnqualifiedDesugaredType ();
466
- if (FieldDecl *FD = createFieldForHostLayoutStruct (
467
- S, Ty, VD->getIdentifier (), LS, BufDecl ))
482
+ if (FieldDecl *FD =
483
+ createFieldForHostLayoutStruct ( S, Ty, VD->getIdentifier (), LS))
468
484
LS->addDecl (FD);
469
485
}
470
486
LS->completeDefinition ();
0 commit comments