Skip to content

Commit 65d20bb

Browse files
authored
[KeyInstr] Disable key-instructions for coroutine scopes (#147551)
At this time (immediately prior to llvm21 branching) we haven't instrumented coroutine generation to identify the "key" instructions of things like co_return and similar. This will lead to worse stepping behaviours, as there won't be any key instruction for those lines. This patch removes the key-instructions flag from the DISubprograms for coroutines, which will cause AsmPrinter to use the "old" / existing linetable stepping behaviour, avoiding a regression until we can instrument these constructs. (I'm going to post on discourse about whether this is a good idea or not in a moment)
1 parent 34bb38f commit 65d20bb

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4629,6 +4629,7 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc,
46294629
llvm::DIFile *Unit = getOrCreateFile(Loc);
46304630
llvm::DIScope *FDContext = Unit;
46314631
llvm::DINodeArray TParamsArray;
4632+
bool KeyInstructions = CGM.getCodeGenOpts().DebugKeyInstructions;
46324633
if (!HasDecl) {
46334634
// Use llvm function name.
46344635
LinkageName = Fn->getName();
@@ -4645,6 +4646,9 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc,
46454646
}
46464647
collectFunctionDeclProps(GD, Unit, Name, LinkageName, FDContext,
46474648
TParamsArray, Flags);
4649+
// Disable KIs if this is a coroutine.
4650+
KeyInstructions =
4651+
KeyInstructions && !isa_and_present<CoroutineBodyStmt>(FD->getBody());
46484652
} else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(D)) {
46494653
Name = getObjCMethodName(OMD);
46504654
Flags |= llvm::DINode::FlagPrototyped;
@@ -4706,7 +4710,7 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc,
47064710
llvm::DISubprogram *SP = DBuilder.createFunction(
47074711
FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine,
47084712
FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl, nullptr,
4709-
Annotations, "", CGM.getCodeGenOpts().DebugKeyInstructions);
4713+
Annotations, "", KeyInstructions);
47104714
Fn->setSubprogram(SP);
47114715

47124716
// We might get here with a VarDecl in the case we're generating
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// RUN: %clang_cc1 -disable-llvm-optzns -std=c++20 \
2+
// RUN: -triple=x86_64 -dwarf-version=4 -debug-info-kind=limited \
3+
// RUN: -emit-llvm -o - %s -gkey-instructions | \
4+
// RUN: FileCheck %s
5+
6+
// Check that for the coroutine below, we mark the created DISubprogram as
7+
// not having key instructions. This will prevent AsmPrinter from trying to
8+
// instrument the linetable with key-instructions for source-locations in
9+
// the coroutine scope.
10+
//
11+
// This is a temporary workaround for key instructions: we can instrument
12+
// coroutine code in the future, but it hasn't been done yet.
13+
//
14+
// File contents copied from coro-dwarf.cpp.
15+
16+
namespace std {
17+
template <typename... T> struct coroutine_traits;
18+
19+
template <class Promise = void> struct coroutine_handle {
20+
coroutine_handle() = default;
21+
static coroutine_handle from_address(void *) noexcept;
22+
};
23+
template <> struct coroutine_handle<void> {
24+
static coroutine_handle from_address(void *) noexcept;
25+
coroutine_handle() = default;
26+
template <class PromiseType>
27+
coroutine_handle(coroutine_handle<PromiseType>) noexcept;
28+
};
29+
} // namespace std
30+
31+
struct suspend_always {
32+
bool await_ready() noexcept;
33+
void await_suspend(std::coroutine_handle<>) noexcept;
34+
void await_resume() noexcept;
35+
};
36+
37+
template <typename... Args> struct std::coroutine_traits<void, Args...> {
38+
struct promise_type {
39+
void get_return_object() noexcept;
40+
suspend_always initial_suspend() noexcept;
41+
suspend_always final_suspend() noexcept;
42+
void return_void() noexcept;
43+
promise_type();
44+
~promise_type() noexcept;
45+
void unhandled_exception() noexcept;
46+
};
47+
};
48+
49+
// TODO: Not supported yet
50+
struct CopyOnly {
51+
int val;
52+
CopyOnly(const CopyOnly &) noexcept;
53+
CopyOnly(CopyOnly &&) = delete;
54+
~CopyOnly();
55+
};
56+
57+
struct MoveOnly {
58+
int val;
59+
MoveOnly(const MoveOnly &) = delete;
60+
MoveOnly(MoveOnly &&) noexcept;
61+
~MoveOnly();
62+
};
63+
64+
struct MoveAndCopy {
65+
int val;
66+
MoveAndCopy(const MoveAndCopy &) noexcept;
67+
MoveAndCopy(MoveAndCopy &&) noexcept;
68+
~MoveAndCopy();
69+
};
70+
71+
void consume(int, int, int) noexcept;
72+
73+
void f_coro(int val, MoveOnly moParam, MoveAndCopy mcParam) {
74+
consume(val, moParam.val, mcParam.val);
75+
co_return;
76+
}
77+
78+
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "f_coro", linkageName: "_Z6f_coroi8MoveOnly11MoveAndCopy"
79+
// CHECK-NOT: keyInstructions:
80+
// CHECK: !DIFil
81+

0 commit comments

Comments
 (0)