Skip to content

Commit 700c1c4

Browse files
committed
[debuginfo][coro] Fix linkage name for clones of coro functions
So far, the `DW_AT_linkage_name` of the coroutine `resume`, `destroy`, `cleanup` and `noalloc` functions were incorrectly set to the original function name instead of the updated function names. With this commit, we now update the `DW_AT_linkage_name` to the correct name. This has multiple benefits: 1. it's easier for me (and other developers) to understand the output of `llvm-dwarf-dump` when coroutines are involved. 2. When hitting a breakpoint, both LLDB and GDB now tell you which clone of the function you are in. E.g., GDB now prints "Breakpoint 1.2, coro_func(int) [clone .resume] (v=43) at ..." instead of "Breakpoint 1.2, coro_func(int) (v=43) at ...". 3. GDB's `info line coro_func` command now allows you to distinguish the multiple different clones of the function. In Swift, the linkage names of the clones were already updated. The comment right above the relevant code in `CoroSplit.cpp` already hinted that the linkage name should probably also be updated in C++. This commit was added in commit 6ce76ff, and back then the corresponding `DW_AT_specification` (i.e., `SP->getDeclaration()`) was not updated, yet, which led to problems for C++. In the meantime, commit ca1a5b3 added code to also update `SP->getDeclaration`, as such there is no reason anymore to not update the linkage name for C++. Note that most test cases used inconsistent function names for the LLVM function vs. the DISubprogram linkage name. clang would never emit such LLVM IR. This confused me initially, and hence I fixed it while updating the test case.
1 parent 73c4929 commit 700c1c4

File tree

6 files changed

+31
-46
lines changed

6 files changed

+31
-46
lines changed

clang/lib/CodeGen/CGVTables.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static void resolveTopLevelMetadata(llvm::Function *Fn,
124124
auto *DIS = Fn->getSubprogram();
125125
if (!DIS)
126126
return;
127-
auto *NewDIS = DIS->replaceWithDistinct(DIS->clone());
127+
auto *NewDIS = llvm::MDNode::replaceWithDistinct(DIS->clone());
128128
VMap.MD()[DIS].reset(NewDIS);
129129

130130
// Find all llvm.dbg.declare intrinsics and resolve the DILocalVariable nodes

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -912,29 +912,14 @@ void coro::BaseCloner::create() {
912912
assert(SP != OrigF.getSubprogram() && SP->isDistinct());
913913
updateScopeLine(ActiveSuspend, *SP);
914914

915-
// Update the linkage name to reflect the modified symbol name. It
916-
// is necessary to update the linkage name in Swift, since the
917-
// mangling changes for resume functions. It might also be the
918-
// right thing to do in C++, but due to a limitation in LLVM's
919-
// AsmPrinter we can only do this if the function doesn't have an
920-
// abstract specification, since the DWARF backend expects the
921-
// abstract specification to contain the linkage name and asserts
922-
// that they are identical.
923-
if (SP->getUnit() &&
924-
SP->getUnit()->getSourceLanguage() == dwarf::DW_LANG_Swift) {
925-
SP->replaceLinkageName(MDString::get(Context, NewF->getName()));
926-
if (auto *Decl = SP->getDeclaration()) {
927-
auto *NewDecl = DISubprogram::get(
928-
Decl->getContext(), Decl->getScope(), Decl->getName(),
929-
NewF->getName(), Decl->getFile(), Decl->getLine(), Decl->getType(),
930-
Decl->getScopeLine(), Decl->getContainingType(),
931-
Decl->getVirtualIndex(), Decl->getThisAdjustment(),
932-
Decl->getFlags(), Decl->getSPFlags(), Decl->getUnit(),
933-
Decl->getTemplateParams(), nullptr, Decl->getRetainedNodes(),
934-
Decl->getThrownTypes(), Decl->getAnnotations(),
935-
Decl->getTargetFuncName());
936-
SP->replaceDeclaration(NewDecl);
937-
}
915+
// Update the linkage name and the functaion name to reflect the modified
916+
// name.
917+
MDString *NewLinkageName = MDString::get(Context, NewF->getName());
918+
SP->replaceLinkageName(NewLinkageName);
919+
if (DISubprogram *Decl = SP->getDeclaration()) {
920+
TempDISubprogram NewDecl = Decl->clone();
921+
NewDecl->replaceLinkageName(NewLinkageName);
922+
SP->replaceDeclaration(MDNode::replaceWithUniqued(std::move(NewDecl)));
938923
}
939924
}
940925

llvm/test/Transforms/Coroutines/coro-debug-dbg.values-not_used_in_frame.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s
33
;
44
; This file is based on coro-debug-frame-variable.ll.
5-
; CHECK: define internal fastcc void @f.resume(ptr noundef nonnull align 16 dereferenceable(80) %begin) !dbg ![[RESUME_FN_DBG_NUM:[0-9]+]]
5+
; CHECK: define internal fastcc void @_Z3foov.resume(ptr noundef nonnull align 16 dereferenceable(80) %begin) !dbg ![[RESUME_FN_DBG_NUM:[0-9]+]]
66
; CHECK: await.ready:
77
; CHECK: #dbg_value(i32 poison, ![[IVAR_RESUME:[0-9]+]], !DIExpression(
88
; CHECK: #dbg_value(i32 poison, ![[JVAR_RESUME:[0-9]+]], !DIExpression(
99
;
10-
; CHECK: ![[RESUME_FN_DBG_NUM]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov"
10+
; CHECK: ![[RESUME_FN_DBG_NUM]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov.resume"
1111
; CHECK: ![[IVAR_RESUME]] = !DILocalVariable(name: "i"
1212
; CHECK: ![[JVAR_RESUME]] = !DILocalVariable(name: "j"
1313

1414
source_filename = "../llvm/test/Transforms/Coroutines/coro-debug-dbg.values-O2.ll"
1515

16-
define void @f(i32 %i, i32 %j) presplitcoroutine !dbg !8 {
16+
define void @_Z3foov(i32 %i, i32 %j) presplitcoroutine !dbg !8 {
1717
entry:
1818
%__promise = alloca i8, align 8
1919
%x = alloca [10 x i32], align 16

llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s
33
;
44
; This file is based on coro-debug-frame-variable.ll.
5-
; CHECK-LABEL: define void @f(
5+
; CHECK-LABEL: define void @_Z3foov(
66
; CHECK: %[[frame:.*]] = call {{.*}} @llvm.coro.begin
77
; CHECK: #dbg_value(ptr %[[frame]]
88
; CHECK-SAME: !DIExpression(DW_OP_plus_uconst, [[OffsetX:[0-9]*]]),
@@ -20,7 +20,7 @@
2020
; CHECK: #dbg_value(ptr %[[frame]]
2121
; CHECK-SAME: !DIExpression(DW_OP_plus_uconst, [[OffsetJ:[0-9]*]], DW_OP_deref),
2222

23-
; CHECK-LABEL: void @f.resume(
23+
; CHECK-LABEL: void @_Z3foov.resume(
2424
; CHECK-SAME: ptr {{.*}} %[[frame:.*]])
2525
; CHECK-SAME: !dbg ![[RESUME_FN_DBG_NUM:[0-9]+]]
2626
; CHECK: %[[frame_alloca:.*]] = alloca ptr
@@ -37,7 +37,7 @@
3737
; CHECK: #dbg_value(ptr %[[frame_alloca]], ![[JVAR_RESUME:[0-9]+]],
3838
; CHECK-SAME: !DIExpression(DW_OP_deref, DW_OP_plus_uconst, [[OffsetJ]], DW_OP_deref)
3939
;
40-
; CHECK: ![[RESUME_FN_DBG_NUM]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov"
40+
; CHECK: ![[RESUME_FN_DBG_NUM]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov.resume"
4141
; CHECK: ![[FRAME_DI_NUM]] = !DILocalVariable(name: "__coro_frame"
4242
; CHECK: ![[IVAR_RESUME]] = !DILocalVariable(name: "i"
4343
; CHECK: ![[XVAR_RESUME]] = !DILocalVariable(name: "x"
@@ -46,7 +46,7 @@
4646

4747
declare void @consume(i32)
4848

49-
define void @f(i32 %i, i32 %j) presplitcoroutine !dbg !8 {
49+
define void @_Z3foov(i32 %i, i32 %j) presplitcoroutine !dbg !8 {
5050
entry:
5151
%__promise = alloca i8, align 8
5252
%x = alloca [10 x i32], align 16
@@ -257,4 +257,4 @@ attributes #4 = { argmemonly nofree nosync nounwind willreturn writeonly }
257257
!21 = !DILocation(line: 43, column: 3, scope: !7)
258258
!22 = !DILocation(line: 43, column: 8, scope: !7)
259259
!23 = !DILocalVariable(name: "produced", scope: !7, file: !1, line:24, type: !10)
260-
!30 = distinct !DIAssignID()
260+
!30 = distinct !DIAssignID()

llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
;
2424
; The CHECKs verify that dbg.declare intrinsics are created for the coroutine
2525
; funclet 'f.resume', and that they reference the address of the variables on
26-
; the coroutine frame. The debug locations for the original function 'f' are
26+
; the coroutine frame. The debug locations for the original function 'foo' are
2727
; static (!11 and !13), whereas the coroutine funclet will have its own new
2828
; ones with identical line and column numbers.
2929
;
30-
; CHECK-LABEL: define void @f() {{.*}} {
30+
; CHECK-LABEL: define void @_Z3foov() {{.*}} {
3131
; CHECK: entry:
3232
; CHECK: %j = alloca i32, align 4
3333
; CHECK: #dbg_declare(ptr %j, ![[JVAR:[0-9]+]], !DIExpression(), ![[JDBGLOC:[0-9]+]]
@@ -36,7 +36,7 @@
3636
; CHECK: #dbg_declare(ptr %[[MEMORY]], ![[IVAR:[0-9]+]], !DIExpression(DW_OP_plus_uconst, 20), ![[IDBGLOC]]
3737
; CHECK: await.ready:
3838
;
39-
; CHECK-LABEL: define internal fastcc void @f.resume({{.*}}) {{.*}} {
39+
; CHECK-LABEL: define internal fastcc void @_Z3foov.resume({{.*}}) {{.*}} {
4040
; CHECK: entry.resume:
4141
; CHECK-NEXT: %[[DBG_PTR:.*]] = alloca ptr
4242
; CHECK-NEXT: #dbg_declare(ptr %[[DBG_PTR]], ![[XVAR_RESUME:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32),
@@ -58,13 +58,13 @@
5858
; CHECK-DAG: ![[JDBGLOC]] = !DILocation(line: 32, column: 7, scope: ![[BLK_SCOPE]])
5959

6060
; CHECK-DAG: ![[XVAR_RESUME]] = !DILocalVariable(name: "x"
61-
; CHECK-DAG: ![[RESUME_PROG_SCOPE:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov"
61+
; CHECK-DAG: ![[RESUME_PROG_SCOPE:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov.resume"
6262
; CHECK-DAG: ![[IDBGLOC_RESUME]] = !DILocation(line: 24, column: 7, scope: ![[RESUME_BLK_SCOPE:[0-9]+]])
6363
; CHECK-DAG: ![[RESUME_BLK_SCOPE]] = distinct !DILexicalBlock(scope: ![[RESUME_PROG_SCOPE]], file: !1, line: 23, column: 12)
6464
; CHECK-DAG: ![[IVAR_RESUME]] = !DILocalVariable(name: "i"
6565
; CHECK-DAG: ![[JVAR_RESUME]] = !DILocalVariable(name: "j"
6666
; CHECK-DAG: ![[JDBGLOC_RESUME]] = !DILocation(line: 32, column: 7, scope: ![[RESUME_BLK_SCOPE]])
67-
define void @f() presplitcoroutine !dbg !8 {
67+
define void @_Z3foov() presplitcoroutine !dbg !8 {
6868
entry:
6969
%__promise = alloca i8, align 8
7070
%i = alloca i32, align 4

llvm/test/Transforms/Coroutines/coro-debug.ll

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
66
target triple = "x86_64-unknown-linux-gnu"
77

88
; Function Attrs: noinline nounwind
9-
define ptr @f(i32 %x) #0 personality i32 0 !dbg !6 {
9+
define ptr @flink(i32 %x) #0 personality i32 0 !dbg !6 {
1010
entry:
1111
%x.addr = alloca i32, align 4
1212
%coro_hdl = alloca ptr, align 8
1313
store i32 %x, ptr %x.addr, align 4
14-
%0 = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr null), !dbg !16
14+
%0 = call token @llvm.coro.id(i32 0, ptr null, ptr @flink, ptr null), !dbg !16
1515
%1 = call i64 @llvm.coro.size.i64(), !dbg !16
1616
%call = call ptr @malloc(i64 %1), !dbg !16
1717
%2 = call ptr @llvm.coro.begin(token %0, ptr %call) #7, !dbg !16
@@ -170,8 +170,8 @@ attributes #7 = { noduplicate }
170170
!31 = !DILocalVariable(name: "allocated", scope: !6, file: !7, line: 55, type: !11)
171171
!32 = !DILocalVariable(name: "inline_asm", scope: !6, file: !7, line: 55, type: !11)
172172

173-
; CHECK: define ptr @f(i32 %x) #0 personality i32 0 !dbg ![[ORIG:[0-9]+]]
174-
; CHECK: define internal fastcc void @f.resume(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[RESUME:[0-9]+]]
173+
; CHECK: define ptr @flink(i32 %x) #0 personality i32 0 !dbg ![[ORIG:[0-9]+]]
174+
; CHECK: define internal fastcc void @flink.resume(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[RESUME:[0-9]+]]
175175
; CHECK: entry.resume:
176176
; CHECK: %[[DBG_PTR:.*]] = alloca ptr
177177
; CHECK: #dbg_declare(ptr %[[DBG_PTR]], ![[RESUME_COROHDL:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst,
@@ -194,18 +194,18 @@ attributes #7 = { noduplicate }
194194
; CHECK: [[DEFAULT_DEST]]:
195195
; CHECK-NOT: {{.*}}:
196196
; CHECK: #dbg_value(i32 %[[CALLBR_RES]]
197-
; CHECK: define internal fastcc void @f.destroy(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[DESTROY:[0-9]+]]
198-
; CHECK: define internal fastcc void @f.cleanup(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[CLEANUP:[0-9]+]]
197+
; CHECK: define internal fastcc void @flink.destroy(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[DESTROY:[0-9]+]]
198+
; CHECK: define internal fastcc void @flink.cleanup(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[CLEANUP:[0-9]+]]
199199

200200
; CHECK: ![[ORIG]] = distinct !DISubprogram(name: "f", linkageName: "flink"
201201

202-
; CHECK: ![[RESUME]] = distinct !DISubprogram(name: "f", linkageName: "flink"
202+
; CHECK: ![[RESUME]] = distinct !DISubprogram(name: "f", linkageName: "flink.resume"
203203
; CHECK: ![[RESUME_COROHDL]] = !DILocalVariable(name: "coro_hdl", scope: ![[RESUME]]
204204
; CHECK: ![[RESUME_X]] = !DILocalVariable(name: "x", arg: 1, scope: ![[RESUME]]
205205
; CHECK: ![[RESUME_CONST]] = !DILocalVariable(name: "direct_const", scope: ![[RESUME]]
206206
; CHECK: ![[RESUME_DIRECT]] = !DILocalVariable(name: "direct_mem", scope: ![[RESUME]]
207207
; CHECK: ![[RESUME_DIRECT_VALUE]] = !DILocalVariable(name: "direct_value", scope: ![[RESUME]]
208208

209-
; CHECK: ![[DESTROY]] = distinct !DISubprogram(name: "f", linkageName: "flink"
209+
; CHECK: ![[DESTROY]] = distinct !DISubprogram(name: "f", linkageName: "flink.destroy"
210210

211-
; CHECK: ![[CLEANUP]] = distinct !DISubprogram(name: "f", linkageName: "flink"
211+
; CHECK: ![[CLEANUP]] = distinct !DISubprogram(name: "f", linkageName: "flink.cleanup"

0 commit comments

Comments
 (0)