-
Notifications
You must be signed in to change notification settings - Fork 13.3k
release/19.x: [RemoveDIs] Fix spliceDebugInfo splice-to-end edge case (#105671) #106691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Fix llvm#105571 which demonstrates an end() iterator dereference when performing a non-empty splice to end() from a region that ends at Src::end(). Rather than calling Instruction::adoptDbgRecords from Dest, create a marker (which takes an iterator) and absorbDebugValues onto that. The "absorb" variant doesn't clean up the source marker, which in this case we know is a trailing marker, so we have to do that manually. (cherry picked from commit 43661a1)
@jmorse What do you think about merging this PR to the release branch? |
@llvm/pr-subscribers-llvm-ir Author: None (llvmbot) ChangesBackport 43661a1 Requested by: @OCHyams Full diff: https://github.com./llvm/llvm-project/pull/106691.diff 2 Files Affected:
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index bf19934da047c4..103ec0da4763fd 100644
--- a/llvm/lib/IR/BasicBlock.cpp
+++ b/llvm/lib/IR/BasicBlock.cpp
@@ -971,8 +971,16 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src,
if (ReadFromTail && Src->getMarker(Last)) {
DbgMarker *FromLast = Src->getMarker(Last);
if (LastIsEnd) {
- Dest->adoptDbgRecords(Src, Last, true);
- // adoptDbgRecords will release any trailers.
+ if (Dest == end()) {
+ // Abosrb the trailing markers from Src.
+ assert(FromLast == Src->getTrailingDbgRecords());
+ createMarker(Dest)->absorbDebugValues(*FromLast, true);
+ FromLast->eraseFromParent();
+ Src->deleteTrailingDbgRecords();
+ } else {
+ // adoptDbgRecords will release any trailers.
+ Dest->adoptDbgRecords(Src, Last, true);
+ }
assert(!Src->getTrailingDbgRecords());
} else {
// FIXME: can we use adoptDbgRecords here to reduce allocations?
diff --git a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp
index 91a0745a0cc76e..e6f8df2762e81e 100644
--- a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp
+++ b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp
@@ -1525,4 +1525,58 @@ TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) {
EXPECT_FALSE(Ret->hasDbgRecords());
}
+TEST(BasicBlockDbgInfoTest, CloneTrailingRecordsToEmptyBlock) {
+ LLVMContext C;
+ std::unique_ptr<Module> M = parseIR(C, R"(
+ define i16 @foo(i16 %a) !dbg !6 {
+ entry:
+ %b = add i16 %a, 0
+ #dbg_value(i16 %b, !9, !DIExpression(), !11)
+ ret i16 0, !dbg !11
+ }
+
+ !llvm.dbg.cu = !{!0}
+ !llvm.module.flags = !{!5}
+
+ !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+ !1 = !DIFile(filename: "t.ll", directory: "/")
+ !2 = !{}
+ !5 = !{i32 2, !"Debug Info Version", i32 3}
+ !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+ !7 = !DISubroutineType(types: !2)
+ !8 = !{!9}
+ !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
+ !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
+ !11 = !DILocation(line: 1, column: 1, scope: !6)
+)");
+ ASSERT_TRUE(M);
+
+ Function *F = M->getFunction("foo");
+ BasicBlock &BB = F->getEntryBlock();
+ // Start with no trailing records.
+ ASSERT_FALSE(BB.getTrailingDbgRecords());
+
+ BasicBlock::iterator Ret = std::prev(BB.end());
+ BasicBlock::iterator B = std::prev(Ret);
+
+ // Delete terminator which has debug records: we now get trailing records.
+ Ret->eraseFromParent();
+ EXPECT_TRUE(BB.getTrailingDbgRecords());
+
+ BasicBlock *NewBB = BasicBlock::Create(C, "NewBB", F);
+ NewBB->splice(NewBB->end(), &BB, B, BB.end());
+
+ // The trailing records should've been absorbed into NewBB.
+ EXPECT_FALSE(BB.getTrailingDbgRecords());
+ EXPECT_TRUE(NewBB->getTrailingDbgRecords());
+ if (NewBB->getTrailingDbgRecords()) {
+ EXPECT_EQ(
+ llvm::range_size(NewBB->getTrailingDbgRecords()->getDbgRecordRange()),
+ 1u);
+ }
+
+ // Drop the trailing records now, to prevent a cleanup assertion.
+ NewBB->deleteTrailingDbgRecords();
+}
+
} // End anonymous namespace.
|
Edge-case |
I feel this is safe to go into the release branch; I don't think it should block the 19.0.0 release though, better to have it in a point release. This fault has been present for roughly five months and has only just been uncovered, so IMHO it's not a pressing issue. |
We are seeing ASAN errors past 43661a1214353ea1773a711f403f8d1118e9ca0f: AddressSanitizer: 120 byte(s) leaked in 2 allocation(s).
|
Thanks for the report, I'll look at that now |
Fixes issue found here #106691 (comment) The issue wasn't in the code change itself, just the unittest; the trailing marker wasn't properly cleaned up.
llvm#106691 (comment) (cherry picked from commit a80307d)
Re-opened backport request with the fix too - #106952 |
Backport 43661a1
Requested by: @OCHyams