================
@@ -4717,6 +4725,157 @@ void SemaHLSL::deduceAddressSpace(VarDecl *Decl) {
Decl->setType(Type);
}
+namespace {
+
+// Creates a global variable declaration for a resource field embedded in a
+// struct, assigns it a binding, initializes it, and associates it with the
+// struct declaration via an HLSLAssociatedResourceDeclAttr.
+static void createGlobalResourceDeclForStruct(Sema &S, VarDecl *ParentVD,
+ SourceLocation Loc,
+ IdentifierInfo *Id,
+ QualType ResTy) {
+ assert(isResourceRecordTypeOrArrayOf(ResTy) &&
+ "expected resource type or array of resources");
+
+ DeclContext *DC = ParentVD->getNonTransparentDeclContext();
+ assert(DC->isTranslationUnit() && "expected translation unit decl context");
+
+ ASTContext &AST = S.getASTContext();
+ VarDecl *ResDecl =
+ VarDecl::Create(AST, DC, Loc, Loc, Id, ResTy, nullptr, SC_None);
+
+ unsigned Range = 1;
+ const HLSLAttributedResourceType *ResHandleTy = nullptr;
+ if (const auto *AT = dyn_cast<ArrayType>(ResTy.getTypePtr())) {
+ const auto *CAT = dyn_cast<ConstantArrayType>(AT);
+ Range = CAT ? CAT->getSize().getZExtValue() : -1;
+ ResHandleTy = getResourceArrayHandleType(ResTy);
+ } else {
+ ResHandleTy = HLSLAttributedResourceType::findHandleTypeOnResource(
+ ResTy.getTypePtr());
+ }
+ // FIXME: Explicit bindings will be handled in a follow-up change. For now
+ // just add an implicit binding attribute.
+ auto *Attr =
+ HLSLResourceBindingAttr::CreateImplicit(S.getASTContext(), "", "0", {});
+ Attr->setBinding(getRegisterType(ResHandleTy), std::nullopt, 0);
+ Attr->setImplicitBindingOrderID(S.HLSL().getNextImplicitBindingOrderID());
+ ResDecl->addAttr(Attr);
+ ResDecl->setImplicit();
+
+ if (Range == 1)
+ S.HLSL().initGlobalResourceDecl(ResDecl);
+ else
+ S.HLSL().initGlobalResourceArrayDecl(ResDecl);
+
+ ParentVD->addAttr(
+ HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
+ DC->addDecl(ResDecl);
+
+ DeclGroupRef DG(ResDecl);
+ S.Consumer.HandleTopLevelDecl(DG);
+}
+
+static void
+handleArrayOfStructWithResources(Sema &S, VarDecl *ParentVD,
+ const ConstantArrayType *CAT,
+ EmbeddedResourceNameBuilder &NameBuilder);
+
+// Scans base and all fields of a struct/class type to find all embedded
+// resources or resource arrays. Creates a global variable for each resource
+// found.
+static void
+handleStructWithResources(Sema &S, VarDecl *ParentVD, const CXXRecordDecl *RD,
+ EmbeddedResourceNameBuilder &NameBuilder) {
+
+ // Scan the base classes.
+ assert(RD->getNumBases() <= 1 && "HLSL doesn't support multiple
inheritance");
+ const auto *BasesIt = RD->bases_begin();
+ if (BasesIt != RD->bases_end()) {
+ QualType QT = BasesIt->getType();
+ if (QT->isHLSLIntangibleType()) {
+ CXXRecordDecl *BaseRD = QT->getAsCXXRecordDecl();
+ NameBuilder.pushBaseName(BaseRD->getName());
+ handleStructWithResources(S, ParentVD, BaseRD, NameBuilder);
+ NameBuilder.pop();
+ }
+ }
+ // Process this class fields.
+ for (const FieldDecl *FD : RD->fields()) {
+ QualType FDTy = FD->getType().getCanonicalType();
+ if (!FDTy->isHLSLIntangibleType())
+ continue;
+
+ NameBuilder.pushName(FD->getName());
+
+ if (isResourceRecordTypeOrArrayOf(FDTy)) {
+ IdentifierInfo *II = NameBuilder.getNameAsIdentifier(S.getASTContext());
+ createGlobalResourceDeclForStruct(S, ParentVD, FD->getLocation(), II,
+ FDTy);
+ } else if (const auto *RD = FDTy->getAsCXXRecordDecl()) {
+ handleStructWithResources(S, ParentVD, RD, NameBuilder);
+
+ } else if (const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
+ assert(!FDTy->isHLSLResourceRecordArray() &&
+ "resource arrays should have been already handled");
+ handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder);
+ }
+ NameBuilder.pop();
+ }
+}
+
+// Processes array of structs with resources.
+static void
+handleArrayOfStructWithResources(Sema &S, VarDecl *ParentVD,
+ const ConstantArrayType *CAT,
+ EmbeddedResourceNameBuilder &NameBuilder) {
+
+ QualType ElementTy = CAT->getElementType().getCanonicalType();
+ assert(ElementTy->isHLSLIntangibleType() && "Expected HLSL intangible type");
+
+ const ConstantArrayType *SubCAT = dyn_cast<ConstantArrayType>(ElementTy);
+ const CXXRecordDecl *ElementRD = ElementTy->getAsCXXRecordDecl();
+
+ if (!SubCAT && !ElementRD)
+ return;
----------------
bogner wrote:
It still worries me a bit that some code change somewhere else could lead to
new types being possible here and that silently ignoring them might not be
correct. I guess if there isn't something reasonable to assert on then we just
have to live with that though...
https://github.com/llvm/llvm-project/pull/184281
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits