2121#include " clang/AST/ASTContext.h"
2222#include " clang/AST/Attrs.inc"
2323#include " clang/AST/Decl.h"
24+ #include " clang/AST/Expr.h"
2425#include " clang/AST/HLSLResource.h"
2526#include " clang/AST/RecursiveASTVisitor.h"
2627#include " clang/AST/Type.h"
@@ -91,6 +92,14 @@ void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
9192 RootSignatureValMD->addOperand (MDVals);
9293}
9394
95+ // Find array variable declaration from DeclRef expression
96+ static const ValueDecl *getArrayDecl (const Expr *E) {
97+ if (const DeclRefExpr *DRE =
98+ dyn_cast_or_null<DeclRefExpr>(E->IgnoreImpCasts ()))
99+ return DRE->getDecl ();
100+ return nullptr ;
101+ }
102+
94103// Find array variable declaration from nested array subscript AST nodes
95104static const ValueDecl *getArrayDecl (const ArraySubscriptExpr *ASE) {
96105 const Expr *E = nullptr ;
@@ -100,9 +109,7 @@ static const ValueDecl *getArrayDecl(const ArraySubscriptExpr *ASE) {
100109 return nullptr ;
101110 ASE = dyn_cast<ArraySubscriptExpr>(E);
102111 }
103- if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E))
104- return DRE->getDecl ();
105- return nullptr ;
112+ return getArrayDecl (E);
106113}
107114
108115// Get the total size of the array, or -1 if the array is unbounded.
@@ -1116,3 +1123,46 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
11161123 }
11171124 return CGF.MakeAddrLValue (TmpVar, ResultTy, AlignmentSource::Decl);
11181125}
1126+
1127+ // If RHSExpr is a global resource array, initialize all of its resources and
1128+ // set them into LHS. Returns false if no copy has been performed and the
1129+ // array copy should be handled by Clang codegen.
1130+ bool CGHLSLRuntime::emitResourceArrayCopy (LValue &LHS, Expr *RHSExpr,
1131+ CodeGenFunction &CGF) {
1132+ QualType ResultTy = RHSExpr->getType ();
1133+ assert ((ResultTy->isHLSLResourceRecordArray ()) && " expected resource array" );
1134+
1135+ // Let Clang codegen handle local and static resource array copies.
1136+ const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(getArrayDecl (RHSExpr));
1137+ if (!ArrayDecl || !ArrayDecl->hasGlobalStorage () ||
1138+ ArrayDecl->getStorageClass () == SC_Static)
1139+ return false ;
1140+
1141+ // Find binding info for the resource array. For implicit binding
1142+ // the HLSLResourceBindingAttr should have been added by SemaHLSL.
1143+ ResourceBindingAttrs Binding (ArrayDecl);
1144+ assert ((Binding.hasBinding ()) &&
1145+ " resource array must have a binding attribute" );
1146+
1147+ // Find the individual resource type.
1148+ ASTContext &AST = ArrayDecl->getASTContext ();
1149+ QualType ResTy = AST.getBaseElementType (ResultTy);
1150+ const auto *ResArrayTy = cast<ConstantArrayType>(ResultTy.getTypePtr ());
1151+
1152+ // Use the provided LHS for the result.
1153+ AggValueSlot ValueSlot = AggValueSlot::forAddr (
1154+ LHS.getAddress (), Qualifiers (), AggValueSlot::IsDestructed_t (true ),
1155+ AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsAliased_t (false ),
1156+ AggValueSlot::DoesNotOverlap);
1157+
1158+ // Create Value for index and total array size (= range size).
1159+ int Size = getTotalArraySize (AST, ResArrayTy);
1160+ llvm::Value *Zero = llvm::ConstantInt::get (CGM.IntTy , 0 );
1161+ llvm::Value *Range = llvm::ConstantInt::get (CGM.IntTy , Size);
1162+
1163+ // Initialize individual resources in the array into LHS.
1164+ std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray (
1165+ CGF, ResTy->getAsCXXRecordDecl (), ResArrayTy, ValueSlot, Range, Zero,
1166+ ArrayDecl->getName (), Binding, {Zero}, RHSExpr->getExprLoc ());
1167+ return EndIndex.has_value ();
1168+ }
0 commit comments