@@ -1104,6 +1104,7 @@ static Instruction *insertSpills(const FrameDataInfo &FrameData,
1104
1104
auto *FramePtr =
1105
1105
cast<Instruction>(Builder.CreateBitCast (CB, FramePtrTy, " FramePtr" ));
1106
1106
DominatorTree DT (*CB->getFunction ());
1107
+ SmallDenseMap<llvm::Value *, llvm::AllocaInst *, 4 > DbgPtrAllocaCache;
1107
1108
1108
1109
// Create a GEP with the given index into the coroutine frame for the original
1109
1110
// value Orig. Appends an extra 0 index for array-allocas, preserving the
@@ -1209,6 +1210,21 @@ static Instruction *insertSpills(const FrameDataInfo &FrameData,
1209
1210
CurrentReload = Builder.CreateLoad (
1210
1211
FrameTy->getElementType (FrameData.getFieldIndex (E.first )), GEP,
1211
1212
E.first ->getName () + Twine (" .reload" ));
1213
+
1214
+ TinyPtrVector<DbgDeclareInst *> DIs = FindDbgDeclareUses (Def);
1215
+ for (DbgDeclareInst *DDI : DIs) {
1216
+ bool AllowUnresolved = false ;
1217
+ // This dbg.declare is preserved for all coro-split function
1218
+ // fragments. It will be unreachable in the main function, and
1219
+ // processed by coro::salvageDebugInfo() by CoroCloner.
1220
+ DIBuilder (*CurrentBlock->getParent ()->getParent (), AllowUnresolved)
1221
+ .insertDeclare (CurrentReload, DDI->getVariable (),
1222
+ DDI->getExpression (), DDI->getDebugLoc (),
1223
+ &*Builder.GetInsertPoint ());
1224
+ // This dbg.declare is for the main function entry point. It
1225
+ // will be deleted in all coro-split functions.
1226
+ coro::salvageDebugInfo (DbgPtrAllocaCache, DDI);
1227
+ }
1212
1228
}
1213
1229
1214
1230
// If we have a single edge PHINode, remove it and replace it with a
@@ -1276,50 +1292,18 @@ static Instruction *insertSpills(const FrameDataInfo &FrameData,
1276
1292
1277
1293
SmallPtrSet<BasicBlock *, 4 > SeenDbgBBs;
1278
1294
TinyPtrVector<DbgDeclareInst *> DIs = FindDbgDeclareUses (Alloca);
1279
- DIBuilder DIB (*Alloca->getModule (), /* AllowUnresolved*/ false );
1280
- Instruction *FirstDbgDecl = nullptr ;
1281
-
1282
- if (!DIs.empty ()) {
1283
- FirstDbgDecl = DIB.insertDeclare (G, DIs.front ()->getVariable (),
1284
- DIs.front ()->getExpression (),
1285
- DIs.front ()->getDebugLoc (), DIs.front ());
1286
- SeenDbgBBs.insert (DIs.front ()->getParent ());
1287
- }
1295
+ if (!DIs.empty ())
1296
+ DIBuilder (*Alloca->getModule (),
1297
+ /* AllowUnresolved*/ false )
1298
+ .insertDeclare (G, DIs.front ()->getVariable (),
1299
+ DIs.front ()->getExpression (),
1300
+ DIs.front ()->getDebugLoc (), DIs.front ());
1288
1301
for (auto *DI : FindDbgDeclareUses (Alloca))
1289
1302
DI->eraseFromParent ();
1290
1303
replaceDbgUsesWithUndef (Alloca);
1291
1304
1292
- for (Instruction *I : UsersToUpdate) {
1305
+ for (Instruction *I : UsersToUpdate)
1293
1306
I->replaceUsesOfWith (Alloca, G);
1294
-
1295
- // After cloning, transformations might not guarantee that all uses
1296
- // of this alloca are dominated by the already existing dbg.declare's,
1297
- // compromising the debug quality. Instead of writing another
1298
- // transformation to patch each clone, go ahead and early populate
1299
- // basic blocks that use such allocas with more debug info.
1300
- if (SeenDbgBBs.count (I->getParent ()))
1301
- continue ;
1302
-
1303
- // If there isn't a prior dbg.declare for this alloca, it probably
1304
- // means the state hasn't changed prior to one of the relevant suspend
1305
- // point for this frame access.
1306
- if (!FirstDbgDecl)
1307
- continue ;
1308
-
1309
- // These instructions are all dominated by the alloca, insert the
1310
- // dbg.value in the beginning of the BB to enhance debugging
1311
- // experience and allow values to be inspected as early as possible.
1312
- // Prefer dbg.value over dbg.declare since it better sets expectations
1313
- // that control flow can be later changed by other passes.
1314
- auto *DI = cast<DbgDeclareInst>(FirstDbgDecl);
1315
- BasicBlock *CurrentBlock = I->getParent ();
1316
- auto *DerefExpr =
1317
- DIExpression::append (DI->getExpression (), dwarf::DW_OP_deref);
1318
- DIB.insertDbgValueIntrinsic (G, DI->getVariable (), DerefExpr,
1319
- DI->getDebugLoc (),
1320
- &*CurrentBlock->getFirstInsertionPt ());
1321
- SeenDbgBBs.insert (CurrentBlock);
1322
- }
1323
1307
}
1324
1308
Builder.SetInsertPoint (FramePtr->getNextNode ());
1325
1309
for (const auto &A : FrameData.Allocas ) {
@@ -2172,6 +2156,58 @@ static void collectFrameAllocas(Function &F, coro::Shape &Shape,
2172
2156
}
2173
2157
}
2174
2158
2159
+ void coro::salvageDebugInfo (
2160
+ SmallDenseMap<llvm::Value *, llvm::AllocaInst *, 4 > &DbgPtrAllocaCache,
2161
+ DbgDeclareInst *DDI, bool LoadFromFramePtr) {
2162
+ Function *F = DDI->getFunction ();
2163
+ IRBuilder<> Builder (F->getContext ());
2164
+ auto InsertPt = F->getEntryBlock ().getFirstInsertionPt ();
2165
+ while (isa<IntrinsicInst>(InsertPt))
2166
+ ++InsertPt;
2167
+ Builder.SetInsertPoint (&F->getEntryBlock (), InsertPt);
2168
+ DIExpression *Expr = DDI->getExpression ();
2169
+ // Follow the pointer arithmetic all the way to the incoming
2170
+ // function argument and convert into a DIExpression.
2171
+ Value *Storage = DDI->getAddress ();
2172
+ while (Storage) {
2173
+ if (auto *LdInst = dyn_cast<LoadInst>(Storage)) {
2174
+ Storage = LdInst->getOperand (0 );
2175
+ } else if (auto *StInst = dyn_cast<StoreInst>(Storage)) {
2176
+ Storage = StInst->getOperand (0 );
2177
+ } else if (auto *GEPInst = dyn_cast<GetElementPtrInst>(Storage)) {
2178
+ Expr = llvm::salvageDebugInfoImpl (*GEPInst, Expr,
2179
+ /* WithStackValue=*/ false );
2180
+ Storage = GEPInst->getOperand (0 );
2181
+ } else if (auto *BCInst = dyn_cast<llvm::BitCastInst>(Storage))
2182
+ Storage = BCInst->getOperand (0 );
2183
+ else
2184
+ break ;
2185
+ }
2186
+ // Store a pointer to the coroutine frame object in an alloca so it
2187
+ // is available throughout the function when producing unoptimized
2188
+ // code. Extending the lifetime this way is correct because the
2189
+ // variable has been declared by a dbg.declare intrinsic.
2190
+ if (auto Arg = dyn_cast_or_null<llvm::Argument>(Storage)) {
2191
+ auto &Cached = DbgPtrAllocaCache[Storage];
2192
+ if (!Cached) {
2193
+ Cached = Builder.CreateAlloca (Storage->getType (), 0 , nullptr ,
2194
+ Arg->getName () + " .debug" );
2195
+ Builder.CreateStore (Storage, Cached);
2196
+ }
2197
+ Storage = Cached;
2198
+ }
2199
+ // The FramePtr object adds one extra layer of indirection that
2200
+ // needs to be unwrapped.
2201
+ if (LoadFromFramePtr)
2202
+ Expr = DIExpression::prepend (Expr, DIExpression::DerefBefore);
2203
+ auto &VMContext = DDI->getFunction ()->getContext ();
2204
+ DDI->setOperand (
2205
+ 0 , MetadataAsValue::get (VMContext, ValueAsMetadata::get (Storage)));
2206
+ DDI->setOperand (2 , MetadataAsValue::get (VMContext, Expr));
2207
+ if (auto *InsertPt = dyn_cast_or_null<Instruction>(Storage))
2208
+ DDI->moveAfter (InsertPt);
2209
+ }
2210
+
2175
2211
void coro::buildCoroutineFrame (Function &F, Shape &Shape) {
2176
2212
eliminateSwiftError (F, Shape);
2177
2213
0 commit comments