@@ -194,6 +194,8 @@ static const ValueDecl *getArrayDecl(ASTContext &AST, const Expr *E) {
194194 E = E->IgnoreImpCasts ();
195195 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
196196 return DRE->getDecl ();
197+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(E))
198+ E = OVE->getSourceExpr ()->IgnoreImpCasts ();
197199 if (isa<MemberExpr>(E))
198200 return findAssociatedResourceDeclForStruct (AST, cast<MemberExpr>(E));
199201 return nullptr ;
@@ -296,12 +298,13 @@ static void callResourceInitMethod(CodeGenFunction &CGF,
296298 CGF.EmitCall (FnInfo, Callee, ReturnValue, Args, nullptr );
297299}
298300
299- // Initializes local resource array variable. For multi-dimensional arrays it
300- // calls itself recursively to initialize its sub-arrays. The Index used in the
301- // resource constructor calls will begin at StartIndex and will be incremented
302- // for each array element. The last used resource Index is returned to the
303- // caller. If the function returns std::nullopt, it indicates an error.
304- static std::optional<llvm::Value *> initializeLocalResourceArray (
301+ // Initializes local resource array variable with global resource array
302+ // elements. For multi-dimensional arrays it calls itself recursively to
303+ // initialize its sub-arrays. The Index used in the resource constructor calls
304+ // will begin at StartIndex and will be incremented for each array element. The
305+ // last used resource Index is returned to the caller. If the function returns
306+ // std::nullopt, it indicates an error.
307+ static std::optional<llvm::Value *> initializeResourceArrayFromGlobal (
305308 CodeGenFunction &CGF, CXXRecordDecl *ResourceDecl,
306309 const ConstantArrayType *ArrayTy, AggValueSlot &ValueSlot,
307310 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
@@ -329,9 +332,10 @@ static std::optional<llvm::Value *> initializeLocalResourceArray(
329332 Index = CGF.Builder .CreateAdd (Index, One);
330333 GEPIndices.back () = llvm::ConstantInt::get (IntTy, I);
331334 }
332- std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray (
333- CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
334- Binding, GEPIndices, ArraySubsExprLoc);
335+ std::optional<llvm::Value *> MaybeIndex =
336+ initializeResourceArrayFromGlobal (
337+ CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index,
338+ ResourceName, Binding, GEPIndices, ArraySubsExprLoc);
335339 if (!MaybeIndex)
336340 return std::nullopt ;
337341 Index = *MaybeIndex;
@@ -1443,7 +1447,7 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
14431447 // needs to be initialized.
14441448 const ConstantArrayType *ArrayTy =
14451449 cast<ConstantArrayType>(ResultTy.getTypePtr ());
1446- std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray (
1450+ std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal (
14471451 CGF, ResourceTy->getAsCXXRecordDecl (), ArrayTy, ValueSlot, Range, Index,
14481452 ArrayDecl->getName (), Binding, {llvm::ConstantInt::get (CGM.IntTy , 0 )},
14491453 ArraySubsExpr->getExprLoc ());
@@ -1453,20 +1457,15 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
14531457 return CGF.MakeAddrLValue (TmpVar, ResultTy, AlignmentSource::Decl);
14541458}
14551459
1456- // If RHSExpr is a global resource array, initialize all of its resources and
1457- // set them into LHS. Returns false if no copy has been performed and the
1458- // array copy should be handled by Clang codegen.
1459- bool CGHLSLRuntime::emitResourceArrayCopy (LValue &LHS, Expr *RHSExpr,
1460- CodeGenFunction &CGF) {
1461- QualType ResultTy = RHSExpr->getType ();
1462- assert (ResultTy->isHLSLResourceRecordArray () && " expected resource array" );
1463-
1464- // Let Clang codegen handle local and static resource array copies.
1465- const VarDecl *ArrayDecl =
1466- dyn_cast_or_null<VarDecl>(getArrayDecl (CGF.CGM .getContext (), RHSExpr));
1467- if (!ArrayDecl || !ArrayDecl->hasGlobalStorage () ||
1468- ArrayDecl->getStorageClass () == SC_Static)
1469- return false ;
1460+ // Initialize all resources of a global resource array into provided slot.
1461+ bool CGHLSLRuntime::initializeGlobalResourceArray (CodeGenFunction &CGF,
1462+ const VarDecl *ArrayDecl,
1463+ SourceLocation Loc,
1464+ AggValueSlot &DestSlot) {
1465+ assert (ArrayDecl->getType ()->isHLSLResourceRecordArray () &&
1466+ ArrayDecl->hasGlobalStorage () &&
1467+ ArrayDecl->getStorageClass () != SC_Static &&
1468+ " expected global non-static resource array" );
14701469
14711470 // Find binding info for the resource array. For implicit binding
14721471 // the HLSLResourceBindingAttr should have been added by SemaHLSL.
@@ -1476,27 +1475,63 @@ bool CGHLSLRuntime::emitResourceArrayCopy(LValue &LHS, Expr *RHSExpr,
14761475
14771476 // Find the individual resource type.
14781477 ASTContext &AST = ArrayDecl->getASTContext ();
1479- QualType ResTy = AST.getBaseElementType (ResultTy);
1480- const auto *ResArrayTy = cast<ConstantArrayType>(ResultTy.getTypePtr ());
1481-
1482- // Use the provided LHS for the result.
1483- AggValueSlot ValueSlot = AggValueSlot::forAddr (
1484- LHS.getAddress (), Qualifiers (), AggValueSlot::IsDestructed_t (true ),
1485- AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsAliased_t (false ),
1486- AggValueSlot::DoesNotOverlap);
1478+ QualType ResTy = AST.getBaseElementType (ArrayDecl->getType ());
1479+ const auto *ResArrayTy =
1480+ cast<ConstantArrayType>(ArrayDecl->getType ().getTypePtr ());
14871481
14881482 // Create Value for index and total array size (= range size).
14891483 int Size = getTotalArraySize (AST, ResArrayTy);
14901484 llvm::Value *Zero = llvm::ConstantInt::get (CGM.IntTy , 0 );
14911485 llvm::Value *Range = llvm::ConstantInt::get (CGM.IntTy , Size);
14921486
1493- // Initialize individual resources in the array into LHS .
1494- std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray (
1495- CGF, ResTy->getAsCXXRecordDecl (), ResArrayTy, ValueSlot , Range, Zero,
1496- ArrayDecl->getName (), Binding, {Zero}, RHSExpr-> getExprLoc () );
1487+ // Initialize individual resources in the array into DestSlot .
1488+ std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal (
1489+ CGF, ResTy->getAsCXXRecordDecl (), ResArrayTy, DestSlot , Range, Zero,
1490+ ArrayDecl->getName (), Binding, {Zero}, Loc );
14971491 return EndIndex.has_value ();
14981492}
14991493
1494+ // If the expression is a global resource array, initialize all of its resources
1495+ // into Dest. Returns false if no initialization has been performed and the
1496+ // array copy should be handled by the default codegen.
1497+ bool CGHLSLRuntime::emitGlobalResourceArray (CodeGenFunction &CGF, const Expr *E,
1498+ AggValueSlot &DestSlot) {
1499+ assert (E->getType ()->isHLSLResourceRecordArray () &&
1500+ " expected resource array" );
1501+
1502+ // Find the array declaration for the expression. Fallback to the default
1503+ // handling if it's not a global resource array.
1504+ const VarDecl *ArrayDecl =
1505+ dyn_cast_or_null<VarDecl>(getArrayDecl (CGF.CGM .getContext (), E));
1506+ if (!ArrayDecl || !ArrayDecl->hasGlobalStorage () ||
1507+ ArrayDecl->getStorageClass () == SC_Static)
1508+ return false ;
1509+
1510+ return initializeGlobalResourceArray (CGF, ArrayDecl, E->getExprLoc (),
1511+ DestSlot);
1512+ }
1513+
1514+ // If the expression is a global resource array, create a temporary and
1515+ // initialize all of its resources, and return it as an LValue. Returns nullopt
1516+ // if no initialization has been performed and the handling should follow the
1517+ // default path.
1518+ std::optional<LValue> CGHLSLRuntime::emitGlobalResourceArrayAsLValue (
1519+ CodeGenFunction &CGF, const VarDecl *ArrayDecl, SourceLocation Loc) {
1520+ assert (ArrayDecl->getType ()->isHLSLResourceRecordArray () &&
1521+ " expected resource array declaration" );
1522+
1523+ if (!ArrayDecl->hasGlobalStorage () ||
1524+ ArrayDecl->getStorageClass () == SC_Static)
1525+ return std::nullopt ;
1526+
1527+ AggValueSlot TmpArraySlot =
1528+ CGF.CreateAggTemp (ArrayDecl->getType (), " tmpResArray" );
1529+ if (initializeGlobalResourceArray (CGF, ArrayDecl, Loc, TmpArraySlot))
1530+ return CGF.MakeAddrLValue (TmpArraySlot.getAddress (), ArrayDecl->getType (),
1531+ AlignmentSource::Decl);
1532+ return std::nullopt ;
1533+ }
1534+
15001535RawAddress CGHLSLRuntime::createBufferMatrixTempAddress (const LValue &LV,
15011536 SourceLocation Loc,
15021537 CodeGenFunction &CGF) {
@@ -1588,18 +1623,16 @@ CGHLSLRuntime::emitResourceMemberExpr(CodeGenFunction &CGF,
15881623 ME->getType ()->isHLSLResourceRecordArray ()) &&
15891624 " expected resource member expression" );
15901625
1591- if (ME->getType ()->isHLSLResourceRecordArray ()) {
1592- // FIXME: Handle member access of the whole array of resources
1593- // (llvm/llvm-project#187087). Access to individual resource array elements
1594- // is already handled in emitResourceArraySubscriptExpr.
1595- return std::nullopt ;
1596- }
1597-
15981626 const VarDecl *ResourceVD =
15991627 findAssociatedResourceDeclForStruct (CGF.CGM .getContext (), ME);
16001628 if (!ResourceVD)
16011629 return std::nullopt ;
16021630
1631+ // Handle member of resource array type.
1632+ if (ResourceVD->getType ()->isHLSLResourceRecordArray ())
1633+ return emitGlobalResourceArrayAsLValue (CGF, ResourceVD, ME->getExprLoc ());
1634+
1635+ // Handle member that is an individual resource.
16031636 GlobalVariable *ResGV =
16041637 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar (ResourceVD));
16051638 const DataLayout &DL = CGM.getDataLayout ();
0 commit comments