Skip to content

Commit 3cac332

Browse files
authored
[Coroutines] Enhance DILabel generation with support for inlined locs (#155989)
This commit fixes an issue in the generation of DILabels. The previous code did not cover cases where the suspend intrinsic had an inlined location. Because of this, it took an incorrect DIScope, that broke an internal pre-condition of `DIBuilder::insertLabel`. This has been addressed by taking the DIScope of the "inlined at" location, which should be the DISubprogram of the function holding the label.
1 parent 24bc566 commit 3cac332

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,14 +1568,20 @@ struct SwitchCoroutineSplitter {
15681568
if (DebugLoc SuspendLoc = S->getDebugLoc()) {
15691569
std::string LabelName =
15701570
("__coro_resume_" + Twine(SuspendIndex)).str();
1571-
DILocation &DILoc = *SuspendLoc;
1571+
// Take the "inlined at" location, if present. This is mandatory as
1572+
// the DILabel insertion checks that the scopes of label and the
1573+
// attached location match. This is not the case when the suspend
1574+
// location has been inlined due to pointing to the original scope.
1575+
DILocation *DILoc = SuspendLoc->getInlinedAt();
1576+
if (!DILoc)
1577+
DILoc = SuspendLoc;
15721578
DILabel *ResumeLabel =
1573-
DBuilder.createLabel(DIS, LabelName, DILoc.getFile(),
1579+
DBuilder.createLabel(DIS, LabelName, DILoc->getFile(),
15741580
SuspendLoc.getLine(), SuspendLoc.getCol(),
15751581
/*IsArtificial=*/true,
15761582
/*CoroSuspendIdx=*/SuspendIndex,
15771583
/*AlwaysPreserve=*/false);
1578-
DBuilder.insertLabel(ResumeLabel, &DILoc, ResumeBB->begin());
1584+
DBuilder.insertLabel(ResumeLabel, DILoc, ResumeBB->begin());
15791585
}
15801586
}
15811587

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
; RUN: opt %s -passes='cgscc(coro-split)' -S | FileCheck %s
2+
3+
source_filename = "coro.c"
4+
5+
; Function Attrs: nounwind uwtable
6+
define ptr @f() #2 !dbg !16 {
7+
entry:
8+
%0 = tail call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr null), !dbg !26
9+
%1 = tail call i64 @llvm.coro.size.i64(), !dbg !26
10+
%frame = tail call ptr @malloc(i64 %1), !dbg !26
11+
%2 = tail call ptr @llvm.coro.begin(token %0, ptr %frame) #3, !dbg !26
12+
br label %loop1, !dbg !27
13+
14+
loop1:
15+
%3 = tail call token @llvm.coro.save(ptr null), !dbg !34
16+
%4 = tail call i8 @llvm.coro.suspend(token %3, i1 false), !dbg !34
17+
switch i8 %4, label %coro_Suspend [
18+
i8 0, label %loop1
19+
i8 1, label %coro_Cleanup
20+
], !dbg !34
21+
22+
coro_Cleanup:
23+
%7 = tail call ptr @llvm.coro.free(token %0, ptr %2), !dbg !37
24+
tail call void @free(ptr nonnull %7), !dbg !37
25+
br label %coro_Suspend, !dbg !37
26+
27+
coro_Suspend:
28+
tail call i1 @llvm.coro.end(ptr null, i1 false, token none) #3, !dbg !40
29+
ret ptr %2, !dbg !41
30+
}
31+
32+
; Check that the resume function contains the `#dbg_label` instructions.
33+
; CHECK-LABEL: define internal fastcc void @f.resume({{.*}})
34+
; CHECK-SAME: !dbg ![[RESUME_SUBPROGRAM:[0-9]+]]
35+
; CHECK: resume.0:
36+
; CHECK-NEXT: #dbg_label(![[RESUME_0:[0-9]+]], ![[RESUME_LABEL_LOC:[0-9]+]])
37+
38+
; Check that the destroy function contains the `#dbg_label` instructions.
39+
; CHECK-LABEL: define internal fastcc void @f.destroy({{.*}})
40+
; CHECK-SAME: !dbg ![[DESTROY_SUBPROGRAM:[0-9]+]]
41+
; CHECK: resume.0:
42+
; CHECK-NEXT: #dbg_label(![[DESTROY_0:[0-9]+]], ![[DESTROY_LABEL_LOC:[0-9]+]])
43+
44+
; Check that the DILabels are correctly based to their "inlined at" location.
45+
; CHECK: ![[RESUME_LABEL_LOC]] = !DILocation(line: 12, column: 6, scope: ![[RESUME_SUBPROGRAM]])
46+
; CHECK: ![[RESUME_0]] = !DILabel(scope: ![[RESUME_SUBPROGRAM]], name: "__coro_resume_0", file: !{{[0-9]*}}, line: 42, column: 2, isArtificial: true, coroSuspendIdx: 0)
47+
48+
; CHECK: ![[DESTROY_LABEL_LOC]] = !DILocation(line: 12, column: 6, scope: ![[DESTROY_SUBPROGRAM]])
49+
; CHECK: ![[DESTROY_0]] = !DILabel(scope: ![[DESTROY_SUBPROGRAM]], name: "__coro_resume_0", file: !{{[0-9]*}}, line: 42, column: 2, isArtificial: true, coroSuspendIdx: 0)
50+
51+
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #4
52+
53+
declare noalias ptr @malloc(i64) local_unnamed_addr #0
54+
declare i64 @llvm.coro.size.i64() #1
55+
declare ptr @llvm.coro.begin(token, ptr writeonly) #0
56+
declare token @llvm.coro.save(ptr) #0
57+
declare i8 @llvm.coro.suspend(token, i1) #0
58+
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #4
59+
declare void @free(ptr nocapture) local_unnamed_addr #0
60+
declare i1 @llvm.coro.end(ptr, i1, token) #0
61+
62+
attributes #0 = { nounwind }
63+
attributes #1 = { nounwind readnone }
64+
attributes #2 = { nounwind uwtable presplitcoroutine }
65+
attributes #3 = { noduplicate }
66+
attributes #4 = { argmemonly nounwind readonly }
67+
68+
!llvm.dbg.cu = !{!0}
69+
!llvm.module.flags = !{!3, !4}
70+
!llvm.ident = !{!5}
71+
72+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 - manually edited", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
73+
!1 = !DIFile(filename: "coro.c", directory: "/home/gor/build/bin")
74+
!2 = !{}
75+
!3 = !{i32 2, !"Dwarf Version", i32 4}
76+
!4 = !{i32 2, !"Debug Info Version", i32 3}
77+
!5 = !{!"clang version 4.0.0 - manually edited"}
78+
!9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
79+
!16 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 8, type: !17, isLocal: false, isDefinition: true, scopeLine: 8, isOptimized: true, unit: !0, retainedNodes: !20)
80+
!17 = !DISubroutineType(types: !18)
81+
!18 = !{!19}
82+
!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64, align: 64)
83+
!20 = !{!21, !22, !24}
84+
!21 = !DILocalVariable(name: "coro_hdl", scope: !16, file: !1, line: 9, type: !19)
85+
!22 = !DILocalVariable(name: "i", scope: !23, file: !1, line: 11, type: !9)
86+
!23 = distinct !DILexicalBlock(scope: !16, file: !1, line: 11, column: 3)
87+
!24 = !DILocalVariable(name: "coro_mem", scope: !16, file: !1, line: 16, type: !19)
88+
!26 = !DILocation(line: 9, column: 3, scope: !16)
89+
!27 = !DILocation(line: 10, column: 8, scope: !23)
90+
!33 = !DILocation(line: 11, column: 6, scope: !23)
91+
!34 = !DILocation(line: 42, column: 2, scope: !100, inlinedAt: !101)
92+
!35 = !DILocation(line: 13, column: 6, scope: !23)
93+
!36 = !DILocation(line: 14, column: 6, scope: !23)
94+
!37 = !DILocation(line: 16, column: 3, scope: !16)
95+
!40 = !DILocation(line: 16, column: 3, scope: !16)
96+
!41 = !DILocation(line: 17, column: 1, scope: !16)
97+
98+
!100 = distinct !DISubprogram(name: "callee", scope: !1, file: !1, line: 8, type: !17, scopeLine: 4, isOptimized: true, unit: !0, retainedNodes: !2)
99+
!101 = !DILocation(line: 12, column: 6, scope: !16)

0 commit comments

Comments
 (0)