================ @@ -253,12 +257,229 @@ static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl) { } } +// Returns true if the array has a zero size = if any of the dimensions is 0 +static bool isZeroSizedArray(const ConstantArrayType *CAT) { + while (CAT && !CAT->isZeroSize()) + CAT = dyn_cast<ConstantArrayType>( + CAT->getElementType()->getUnqualifiedDesugaredType()); + return CAT != nullptr; +} + +// Returns true if the struct contains at least one element that prevents it +// from being included inside HLSL Buffer as is, such as an intangible type, +// empty struct, or zero-sized array. If it does, a new implicit layout struct +// needs to be created for HLSL Buffer use that will exclude these unwanted +// declarations (see createHostLayoutStruct function). +static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD) { + if (RD->getTypeForDecl()->isHLSLIntangibleType() || RD->isEmpty()) + return true; + // check fields + for (const FieldDecl *Field : RD->fields()) { + QualType Ty = Field->getType(); + if (Ty->isRecordType()) { + if (requiresImplicitBufferLayoutStructure(Ty->getAsCXXRecordDecl())) + return true; + } else if (Ty->isConstantArrayType()) { + if (isZeroSizedArray(cast<ConstantArrayType>(Ty))) + return true; + } + } + // check bases + for (const CXXBaseSpecifier &Base : RD->bases()) + if (requiresImplicitBufferLayoutStructure( + Base.getType()->getAsCXXRecordDecl())) + return true; + return false; +} + +static CXXRecordDecl *findRecordDecl(Sema &S, IdentifierInfo *II, + DeclContext *DC) { + DeclarationNameInfo NameInfo = + DeclarationNameInfo(DeclarationName(II), SourceLocation()); + LookupResult R(S, NameInfo, Sema::LookupOrdinaryName); + S.LookupName(R, S.getScopeForContext(DC)); + if (R.isSingleResult()) + return R.getAsSingle<CXXRecordDecl>(); + return nullptr; +} + +// Creates a name for buffer layout struct using the provide name base. +// If the name must be unique (not previously defined), a suffix is added +// until a unique name is found. +static IdentifierInfo *getHostLayoutStructName(Sema &S, + IdentifierInfo *NameBaseII, + bool MustBeUnique, + DeclContext *DC) { + ASTContext &AST = S.getASTContext(); + std::string NameBase; + if (NameBaseII) { + NameBase = NameBaseII->getName().str(); + } else { + // anonymous struct + NameBase = "anon"; + MustBeUnique = true; + } + + std::string Name = "__layout_" + NameBase; + IdentifierInfo *II = &AST.Idents.get(Name, tok::TokenKind::identifier); + if (!MustBeUnique) + return II; + + unsigned suffix = 0; + while (true) { + if (suffix != 0) + II = &AST.Idents.get((llvm::Twine(Name) + "_" + Twine(suffix)).str(), + tok::TokenKind::identifier); + if (!findRecordDecl(S, II, DC)) + return II; + // declaration with that name already exists - increment suffix and try + // again until unique name is found + suffix++; + }; +} + +// Returns true if the record type is an HLSL resource class +static bool isResourceRecordType(const Type *Ty) { + return HLSLAttributedResourceType::findHandleTypeOnResource(Ty) != nullptr; +} + +static CXXRecordDecl *createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl, + HLSLBufferDecl *BufDecl); + +// Creates a field declaration of given name and type for HLSL buffer layout +// struct. Returns nullptr if the type cannot be use in HLSL Buffer layout. +static FieldDecl *createFieldForHostLayoutStruct(Sema &S, const Type *Ty, + IdentifierInfo *II, + CXXRecordDecl *LayoutStruct, + HLSLBufferDecl *BufDecl) { + if (Ty->isRecordType()) { + if (isResourceRecordType(Ty)) ---------------- hekota wrote:
There is an assert at the top of the `createHostLayoutStruct` function that will make sure the logic is consistent: ``` assert(requiresImplicitBufferLayoutStructure(StructDecl) && "struct is already HLSL buffer compatible"); ``` I have also moved the checking into a shared function `isInvalidConstantBufferLeafElementType`. Currently the only intangible types are resources classes, but I added a check for builtin resource type as well. https://github.com/llvm/llvm-project/pull/122820 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits