@@ -804,6 +804,7 @@ static Instruction *insertSpills(const SpillInfo &Spills, coro::Shape &Shape) {
804
804
CurrentValue->getName () + Twine (" .reload" ));
805
805
};
806
806
807
+ SmallDenseMap<llvm::Value *, llvm::AllocaInst *, 4 > DbgPtrAllocaCache;
807
808
Value *GEP = nullptr , *CurrentGEP = nullptr ;
808
809
for (auto const &E : Spills) {
809
810
// If we have not seen the value, generate a spill.
@@ -896,12 +897,21 @@ static Instruction *insertSpills(const SpillInfo &Spills, coro::Shape &Shape) {
896
897
if (CurrentGEP != GEP) {
897
898
CurrentGEP = GEP;
898
899
TinyPtrVector<DbgDeclareInst *> DIs = FindDbgDeclareUses (CurrentValue);
899
- if (!DIs.empty ())
900
- DIBuilder (*CurrentBlock->getParent ()->getParent (),
901
- /* AllowUnresolved*/ false )
902
- .insertDeclare (CurrentGEP, DIs.front ()->getVariable (),
903
- DIs.front ()->getExpression (),
904
- DIs.front ()->getDebugLoc (), DIs.front ());
900
+ if (!DIs.empty ()) {
901
+ auto *DDI = DIs.front ();
902
+ bool AllowUnresolved = false ;
903
+ // This dbg.declare is preserved for all coro-split function
904
+ // fragments. It will be unreachable in the main function, and
905
+ // processed by coro::salvageDebugInfo() by CoroCloner.
906
+ DIBuilder (*CurrentBlock->getParent ()->getParent (), AllowUnresolved)
907
+ .insertDeclare (CurrentGEP, DDI->getVariable (),
908
+ DDI->getExpression (),
909
+ DDI->getDebugLoc (),
910
+ &*Builder.GetInsertPoint ());
911
+ // This dbg.declare is for the main function entry point. It
912
+ // will be deleted in all coro-split functions.
913
+ coro::salvageDebugInfo (DbgPtrAllocaCache, DDI);
914
+ }
905
915
}
906
916
907
917
// Replace all uses of CurrentValue in the current instruction with reload.
@@ -1633,6 +1643,55 @@ static void sinkLifetimeStartMarkers(Function &F, coro::Shape &Shape,
1633
1643
}
1634
1644
}
1635
1645
1646
+ void coro::salvageDebugInfo (
1647
+ SmallDenseMap<llvm::Value *, llvm::AllocaInst *, 4 > &DbgPtrAllocaCache,
1648
+ DbgDeclareInst *DDI, bool LoadFromFramePtr) {
1649
+ Function *F = DDI->getFunction ();
1650
+ IRBuilder<> Builder (F->getContext ());
1651
+ auto InsertPt = F->getEntryBlock ().getFirstInsertionPt ();
1652
+ while (isa<IntrinsicInst>(InsertPt))
1653
+ ++InsertPt;
1654
+ Builder.SetInsertPoint (&F->getEntryBlock (), InsertPt);
1655
+ DIExpression *Expr = DDI->getExpression ();
1656
+ // Follow the pointer arithmetic all the way to the incoming
1657
+ // function argument and convert into a DIExpression.
1658
+ Value *Storage = DDI->getAddress ();
1659
+ while (Storage) {
1660
+ if (auto *LdInst = dyn_cast<LoadInst>(Storage)) {
1661
+ Storage = LdInst->getOperand (0 );
1662
+ } else if (auto *GEPInst = dyn_cast<GetElementPtrInst>(Storage)) {
1663
+ Expr = llvm::salvageDebugInfoImpl (*GEPInst, Expr,
1664
+ /* WithStackValue=*/ false );
1665
+ Storage = GEPInst->getOperand (0 );
1666
+ } else if (auto *BCInst = dyn_cast<llvm::BitCastInst>(Storage))
1667
+ Storage = BCInst->getOperand (0 );
1668
+ else
1669
+ break ;
1670
+ }
1671
+ // Store a pointer to the coroutine frame object in an alloca so it
1672
+ // is available throughout the function when producing unoptimized
1673
+ // code. Extending the lifetime this way is correct because the
1674
+ // variable has been declared by a dbg.declare intrinsic.
1675
+ if (auto Arg = dyn_cast_or_null<llvm::Argument>(Storage)) {
1676
+ auto &Cached = DbgPtrAllocaCache[Storage];
1677
+ if (!Cached) {
1678
+ Cached = Builder.CreateAlloca (Storage->getType (), 0 , nullptr ,
1679
+ Arg->getName () + " .debug" );
1680
+ Builder.CreateStore (Storage, Cached);
1681
+ }
1682
+ Storage = Cached;
1683
+ Expr = DIExpression::prepend (Expr, DIExpression::DerefBefore);
1684
+ }
1685
+ // The FramePtr object adds one extra layer of indirection that
1686
+ // needs to be unwrapped.
1687
+ if (LoadFromFramePtr)
1688
+ Expr = DIExpression::prepend (Expr, DIExpression::DerefBefore);
1689
+ auto &VMContext = DDI->getFunction ()->getContext ();
1690
+ DDI->setOperand (
1691
+ 0 , MetadataAsValue::get (VMContext, ValueAsMetadata::get (Storage)));
1692
+ DDI->setOperand (2 , MetadataAsValue::get (VMContext, Expr));
1693
+ }
1694
+
1636
1695
void coro::buildCoroutineFrame (Function &F, Shape &Shape) {
1637
1696
eliminateSwiftError (F, Shape);
1638
1697
0 commit comments