Skip to content

Commit 8629fc6

Browse files
committed
[debuginfo][coro] Emit debug info labels for coroutine resume points
With this commit, we add `DILabel` debug infos (lowering to DW_TAG_label in DWARF) to the various resume points of a coroutine. Those labels use the naming convention `__coro_resume_<N>` where `<N>` is the suspension point id. That way, debugging scripts can figure out the exact line / column at which a coroutine was suspended by looking up current `__coro_index` value inside the coroutines frame, and then searching for the corresponding `__coro_resume_<N>` inside the coroutine's resume function. While this is an artificial compiler-generated label, I did not apply the DW_AT_artificial tag to it. The DWARFv5 standard only allows that tag on type and variable definitions, but not on labels. In gdb, those line numebers can then be looked up using the command `info line -function my_coroutine -label __coro_resume_1`. LLDB unfortunately does not parse DW_TAG_label debug information, yet. As such, this debug information is currently not useful in LLDB.
1 parent 73c4929 commit 8629fc6

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -689,9 +689,8 @@ static DIType *solveDIType(DIBuilder &Builder, Type *Ty,
689689
static void buildFrameDebugInfo(Function &F, coro::Shape &Shape,
690690
FrameDataInfo &FrameData) {
691691
DISubprogram *DIS = F.getSubprogram();
692-
// If there is no DISubprogram for F, it implies the Function are not compiled
693-
// with debug info. So we also don't need to generate debug info for the frame
694-
// neither.
692+
// If there is no DISubprogram for F, it implies the function is compiled without
693+
// debug info. So we also don't generate debug info for the frame, either.
695694
if (!DIS || !DIS->getUnit() ||
696695
!dwarf::isCPlusPlus(
697696
(dwarf::SourceLanguage)DIS->getUnit()->getSourceLanguage()) ||

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "llvm/IR/CFG.h"
4343
#include "llvm/IR/CallingConv.h"
4444
#include "llvm/IR/Constants.h"
45+
#include "llvm/IR/DIBuilder.h"
4546
#include "llvm/IR/DataLayout.h"
4647
#include "llvm/IR/DebugInfo.h"
4748
#include "llvm/IR/DerivedTypes.h"
@@ -302,7 +303,7 @@ static void replaceFallthroughCoroEnd(AnyCoroEndInst *End,
302303
}
303304

304305
// Mark a coroutine as done, which implies that the coroutine is finished and
305-
// never get resumed.
306+
// never gets resumed.
306307
//
307308
// In resume-switched ABI, the done state is represented by storing zero in
308309
// ResumeFnAddr.
@@ -1492,6 +1493,14 @@ struct SwitchCoroutineSplitter {
14921493
static void createResumeEntryBlock(Function &F, coro::Shape &Shape) {
14931494
LLVMContext &C = F.getContext();
14941495

1496+
DIBuilder DBuilder(*F.getParent(), /*AllowUnresolved*/ false);
1497+
DISubprogram *DIS = F.getSubprogram();
1498+
// If there is no DISubprogram for F, it implies the function is compiled without
1499+
// debug info. So we also don't generate debug info for the suspension points, either.
1500+
bool AddDebugLabels = (DIS && DIS->getUnit() &&
1501+
(DIS->getUnit()->getEmissionKind() == DICompileUnit::DebugEmissionKind::FullDebug ||
1502+
DIS->getUnit()->getEmissionKind() == DICompileUnit::DebugEmissionKind::LineTablesOnly));
1503+
14951504
// resume.entry:
14961505
// %index.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32
14971506
// 0, i32 2 % index = load i32, i32* %index.addr switch i32 %index, label
@@ -1514,6 +1523,7 @@ struct SwitchCoroutineSplitter {
15141523
Builder.CreateSwitch(Index, UnreachBB, Shape.CoroSuspends.size());
15151524
Shape.SwitchLowering.ResumeSwitch = Switch;
15161525

1526+
// Split all coro.suspend calls
15171527
size_t SuspendIndex = 0;
15181528
for (auto *AnyS : Shape.CoroSuspends) {
15191529
auto *S = cast<CoroSuspendInst>(AnyS);
@@ -1552,6 +1562,7 @@ struct SwitchCoroutineSplitter {
15521562
// br label %resume.0.landing
15531563
//
15541564
// resume.0: ; <--- jump from the switch in the resume.entry
1565+
// XXX: label
15551566
// %0 = tail call i8 @llvm.coro.suspend(token none, i1 false)
15561567
// br label %resume.0.landing
15571568
//
@@ -1574,11 +1585,21 @@ struct SwitchCoroutineSplitter {
15741585
PN->addIncoming(Builder.getInt8(-1), SuspendBB);
15751586
PN->addIncoming(S, ResumeBB);
15761587

1588+
if (AddDebugLabels) {
1589+
if (DebugLoc SuspendLoc = S->getDebugLoc()) {
1590+
std::string labelName = ("__coro_resume_" + Twine(SuspendIndex)).str();
1591+
DILocation& DILoc = *SuspendLoc.get();
1592+
DILabel *ResumeLabel = DBuilder.createLabel(DIS, labelName, DILoc.getFile(), SuspendLoc.getLine());
1593+
DBuilder.insertLabel(ResumeLabel, &DILoc, ResumeBB->begin());
1594+
}
1595+
}
1596+
15771597
++SuspendIndex;
15781598
}
15791599

15801600
Builder.SetInsertPoint(UnreachBB);
15811601
Builder.CreateUnreachable();
1602+
DBuilder.finalize();
15821603

15831604
Shape.SwitchLowering.ResumeEntryBlock = NewEntry;
15841605
}

0 commit comments

Comments
 (0)