Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / unittests / IR / BasicBlockDbgInfoTest.cpp
blob91a0745a0cc76e48ef4b518e4ac5da48f637a979
1 //===- llvm/unittest/IR/BasicBlockTest.cpp - BasicBlock unit tests --------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/BasicBlock.h"
10 #include "llvm/IR/DebugInfo.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/IRBuilder.h"
15 #include "llvm/IR/Instruction.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/IR/NoFolder.h"
20 #include "llvm/IR/Verifier.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "gmock/gmock-matchers.h"
23 #include "gtest/gtest.h"
24 #include <memory>
26 using namespace llvm;
28 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
29 SMDiagnostic Err;
30 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
31 if (!Mod)
32 Err.print("BasicBlockDbgInfoTest", errs());
33 return Mod;
36 namespace {
38 // We can occasionally moveAfter an instruction so that it moves to the
39 // position that it already resides at. This is fine -- but gets complicated
40 // with dbg.value intrinsics. By moving an instruction, we can end up changing
41 // nothing but the location of debug-info intrinsics. That has to be modelled
42 // by DbgVariableRecords, the dbg.value replacement.
43 TEST(BasicBlockDbgInfoTest, InsertAfterSelf) {
44 LLVMContext C;
45 std::unique_ptr<Module> M = parseIR(C, R"(
46 define i16 @f(i16 %a) !dbg !6 {
47 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
48 %b = add i16 %a, 1, !dbg !11
49 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
50 %c = add i16 %b, 1, !dbg !11
51 ret i16 0, !dbg !11
53 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
54 attributes #0 = { nounwind readnone speculatable willreturn }
56 !llvm.dbg.cu = !{!0}
57 !llvm.module.flags = !{!5}
59 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
60 !1 = !DIFile(filename: "t.ll", directory: "/")
61 !2 = !{}
62 !5 = !{i32 2, !"Debug Info Version", i32 3}
63 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
64 !7 = !DISubroutineType(types: !2)
65 !8 = !{!9}
66 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
67 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
68 !11 = !DILocation(line: 1, column: 1, scope: !6)
69 )");
71 // Fetch the entry block.
72 BasicBlock &BB = M->getFunction("f")->getEntryBlock();
74 Instruction *Inst1 = &*BB.begin();
75 Instruction *Inst2 = &*std::next(BB.begin());
76 Instruction *RetInst = &*std::next(Inst2->getIterator());
77 EXPECT_TRUE(Inst1->hasDbgRecords());
78 EXPECT_TRUE(Inst2->hasDbgRecords());
79 EXPECT_FALSE(RetInst->hasDbgRecords());
81 // If we move Inst2 to be after Inst1, then it comes _immediately_ after. Were
82 // we in dbg.value form we would then have:
83 // dbg.value
84 // %b = add
85 // %c = add
86 // dbg.value
87 // Check that this is replicated by DbgVariableRecords.
88 Inst2->moveAfter(Inst1);
90 // Inst1 should only have one DbgVariableRecord on it.
91 EXPECT_TRUE(Inst1->hasDbgRecords());
92 auto Range1 = Inst1->getDbgRecordRange();
93 EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), 1u);
94 // Inst2 should have none.
95 EXPECT_FALSE(Inst2->hasDbgRecords());
96 // While the return inst should now have one on it.
97 EXPECT_TRUE(RetInst->hasDbgRecords());
98 auto Range2 = RetInst->getDbgRecordRange();
99 EXPECT_EQ(std::distance(Range2.begin(), Range2.end()), 1u);
102 TEST(BasicBlockDbgInfoTest, SplitBasicBlockBefore) {
103 LLVMContext C;
104 std::unique_ptr<Module> M = parseIR(C, R"---(
105 define dso_local void @func() #0 !dbg !10 {
106 %1 = alloca i32, align 4
107 tail call void @llvm.dbg.declare(metadata ptr %1, metadata !14, metadata !DIExpression()), !dbg !16
108 store i32 2, ptr %1, align 4, !dbg !16
109 ret void, !dbg !17
112 declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
114 attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
116 !llvm.dbg.cu = !{!0}
117 !llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
118 !llvm.ident = !{!9}
120 !0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "dummy", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
121 !1 = !DIFile(filename: "dummy", directory: "dummy")
122 !2 = !{i32 7, !"Dwarf Version", i32 5}
123 !3 = !{i32 2, !"Debug Info Version", i32 3}
124 !4 = !{i32 1, !"wchar_size", i32 4}
125 !5 = !{i32 8, !"PIC Level", i32 2}
126 !6 = !{i32 7, !"PIE Level", i32 2}
127 !7 = !{i32 7, !"uwtable", i32 2}
128 !8 = !{i32 7, !"frame-pointer", i32 2}
129 !9 = !{!"dummy"}
130 !10 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)
131 !11 = !DISubroutineType(types: !12)
132 !12 = !{null}
133 !13 = !{}
134 !14 = !DILocalVariable(name: "a", scope: !10, file: !1, line: 2, type: !15)
135 !15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
136 !16 = !DILocation(line: 2, column: 6, scope: !10)
137 !17 = !DILocation(line: 3, column: 2, scope: !10)
138 )---");
139 ASSERT_TRUE(M);
141 Function *F = M->getFunction("func");
143 BasicBlock &BB = F->getEntryBlock();
144 auto I = std::prev(BB.end(), 2);
145 BB.splitBasicBlockBefore(I, "before");
147 BasicBlock &BBBefore = F->getEntryBlock();
148 auto I2 = std::prev(BBBefore.end(), 2);
149 ASSERT_TRUE(I2->hasDbgRecords());
152 TEST(BasicBlockDbgInfoTest, MarkerOperations) {
153 LLVMContext C;
154 std::unique_ptr<Module> M = parseIR(C, R"(
155 define i16 @f(i16 %a) !dbg !6 {
156 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
157 %b = add i16 %a, 1, !dbg !11
158 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
159 ret i16 0, !dbg !11
161 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
162 attributes #0 = { nounwind readnone speculatable willreturn }
164 !llvm.dbg.cu = !{!0}
165 !llvm.module.flags = !{!5}
167 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
168 !1 = !DIFile(filename: "t.ll", directory: "/")
169 !2 = !{}
170 !5 = !{i32 2, !"Debug Info Version", i32 3}
171 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
172 !7 = !DISubroutineType(types: !2)
173 !8 = !{!9}
174 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
175 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
176 !11 = !DILocation(line: 1, column: 1, scope: !6)
177 )");
179 // Fetch the entry block,
180 BasicBlock &BB = M->getFunction("f")->getEntryBlock();
181 EXPECT_EQ(BB.size(), 2u);
183 // Fetch out our two markers,
184 Instruction *Instr1 = &*BB.begin();
185 Instruction *Instr2 = Instr1->getNextNode();
186 DbgMarker *Marker1 = Instr1->DebugMarker;
187 DbgMarker *Marker2 = Instr2->DebugMarker;
188 // There's no TrailingDbgRecords marker allocated yet.
189 DbgMarker *EndMarker = nullptr;
191 // Check that the "getMarker" utilities operate as expected.
192 EXPECT_EQ(BB.getMarker(Instr1->getIterator()), Marker1);
193 EXPECT_EQ(BB.getMarker(Instr2->getIterator()), Marker2);
194 EXPECT_EQ(BB.getNextMarker(Instr1), Marker2);
195 EXPECT_EQ(BB.getNextMarker(Instr2), EndMarker); // Is nullptr.
197 // There should be two DbgVariableRecords,
198 EXPECT_EQ(Marker1->StoredDbgRecords.size(), 1u);
199 EXPECT_EQ(Marker2->StoredDbgRecords.size(), 1u);
201 // Unlink them and try to re-insert them through the basic block.
202 DbgRecord *DVR1 = &*Marker1->StoredDbgRecords.begin();
203 DbgRecord *DVR2 = &*Marker2->StoredDbgRecords.begin();
204 DVR1->removeFromParent();
205 DVR2->removeFromParent();
206 EXPECT_TRUE(Marker1->StoredDbgRecords.empty());
207 EXPECT_TRUE(Marker2->StoredDbgRecords.empty());
209 // This should appear in Marker1.
210 BB.insertDbgRecordBefore(DVR1, BB.begin());
211 EXPECT_EQ(Marker1->StoredDbgRecords.size(), 1u);
212 EXPECT_EQ(DVR1, &*Marker1->StoredDbgRecords.begin());
214 // This should attach to Marker2.
215 BB.insertDbgRecordAfter(DVR2, &*BB.begin());
216 EXPECT_EQ(Marker2->StoredDbgRecords.size(), 1u);
217 EXPECT_EQ(DVR2, &*Marker2->StoredDbgRecords.begin());
219 // Now, how about removing instructions? That should cause any
220 // DbgVariableRecords to "fall down".
221 Instr1->removeFromParent();
222 Marker1 = nullptr;
223 // DbgVariableRecords should now be in Marker2.
224 EXPECT_EQ(BB.size(), 1u);
225 EXPECT_EQ(Marker2->StoredDbgRecords.size(), 2u);
226 // They should also be in the correct order.
227 SmallVector<DbgRecord *, 2> DVRs;
228 for (DbgRecord &DVR : Marker2->getDbgRecordRange())
229 DVRs.push_back(&DVR);
230 EXPECT_EQ(DVRs[0], DVR1);
231 EXPECT_EQ(DVRs[1], DVR2);
233 // If we remove the end instruction, the DbgVariableRecords should fall down
234 // into the trailing marker.
235 EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr);
236 Instr2->removeFromParent();
237 EXPECT_TRUE(BB.empty());
238 EndMarker = BB.getTrailingDbgRecords();
239 ASSERT_NE(EndMarker, nullptr);
240 EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u);
241 // Again, these should arrive in the correct order.
243 DVRs.clear();
244 for (DbgRecord &DVR : EndMarker->getDbgRecordRange())
245 DVRs.push_back(&DVR);
246 EXPECT_EQ(DVRs[0], DVR1);
247 EXPECT_EQ(DVRs[1], DVR2);
249 // Inserting a normal instruction at the beginning: shouldn't dislodge the
250 // DbgVariableRecords. It's intended to not go at the start.
251 Instr1->insertBefore(BB, BB.begin());
252 EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u);
253 Instr1->removeFromParent();
255 // Inserting at end(): should dislodge the DbgVariableRecords, if they were
256 // dbg.values then they would sit "above" the new instruction.
257 Instr1->insertBefore(BB, BB.end());
258 EXPECT_EQ(Instr1->DebugMarker->StoredDbgRecords.size(), 2u);
259 // We should de-allocate the trailing marker when something is inserted
260 // at end().
261 EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr);
263 // Remove Instr1: now the DbgVariableRecords will fall down again,
264 Instr1->removeFromParent();
265 EndMarker = BB.getTrailingDbgRecords();
266 EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u);
268 // Inserting a terminator, however it's intended, should dislodge the
269 // trailing DbgVariableRecords, as it's the clear intention of the caller that
270 // this be the final instr in the block, and DbgVariableRecords aren't allowed
271 // to live off the end forever.
272 Instr2->insertBefore(BB, BB.begin());
273 EXPECT_EQ(Instr2->DebugMarker->StoredDbgRecords.size(), 2u);
274 EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr);
276 // Teardown,
277 Instr1->insertBefore(BB, BB.begin());
280 TEST(BasicBlockDbgInfoTest, HeadBitOperations) {
281 LLVMContext C;
282 std::unique_ptr<Module> M = parseIR(C, R"(
283 define i16 @f(i16 %a) !dbg !6 {
284 %b = add i16 %a, 1, !dbg !11
285 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
286 %c = add i16 %a, 1, !dbg !11
287 %d = add i16 %a, 1, !dbg !11
288 ret i16 0, !dbg !11
290 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
291 attributes #0 = { nounwind readnone speculatable willreturn }
293 !llvm.dbg.cu = !{!0}
294 !llvm.module.flags = !{!5}
296 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
297 !1 = !DIFile(filename: "t.ll", directory: "/")
298 !2 = !{}
299 !5 = !{i32 2, !"Debug Info Version", i32 3}
300 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
301 !7 = !DISubroutineType(types: !2)
302 !8 = !{!9}
303 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
304 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
305 !11 = !DILocation(line: 1, column: 1, scope: !6)
306 )");
308 // Test that the movement of debug-data when using moveBefore etc and
309 // insertBefore etc are governed by the "head" bit of iterators.
310 BasicBlock &BB = M->getFunction("f")->getEntryBlock();
312 // Test that the head bit behaves as expected: it should be set when the
313 // code wants the _start_ of the block, but not otherwise.
314 EXPECT_TRUE(BB.getFirstInsertionPt().getHeadBit());
315 BasicBlock::iterator BeginIt = BB.begin();
316 EXPECT_TRUE(BeginIt.getHeadBit());
317 // If you launder the instruction pointer through dereferencing and then
318 // get the iterator again with getIterator, the head bit is lost. This is
319 // deliberate: if you're calling getIterator, then you're requesting an
320 // iterator for the position of _this_ instruction, not "the start of this
321 // block".
322 BasicBlock::iterator BeginIt2 = BeginIt->getIterator();
323 EXPECT_FALSE(BeginIt2.getHeadBit());
325 // Fetch some instruction pointers.
326 Instruction *BInst = &*BeginIt;
327 Instruction *CInst = BInst->getNextNode();
328 Instruction *DInst = CInst->getNextNode();
329 // CInst should have debug-info.
330 ASSERT_TRUE(CInst->DebugMarker);
331 EXPECT_FALSE(CInst->DebugMarker->StoredDbgRecords.empty());
333 // If we move "c" to the start of the block, just normally, then the
334 // DbgVariableRecords should fall down to "d".
335 CInst->moveBefore(BB, BeginIt2);
336 EXPECT_TRUE(!CInst->DebugMarker ||
337 CInst->DebugMarker->StoredDbgRecords.empty());
338 ASSERT_TRUE(DInst->DebugMarker);
339 EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty());
341 // Wheras if we move D to the start of the block with moveBeforePreserving,
342 // the DbgVariableRecords should move with it.
343 DInst->moveBeforePreserving(BB, BB.begin());
344 EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty());
345 EXPECT_EQ(&*BB.begin(), DInst);
347 // Similarly, moveAfterPreserving "D" to "C" should move DbgVariableRecords
348 // with "D".
349 DInst->moveAfterPreserving(CInst);
350 EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty());
352 // (move back to the start...)
353 DInst->moveBeforePreserving(BB, BB.begin());
355 // Current order of insts: "D -> C -> B -> Ret". DbgVariableRecords on "D".
356 // If we move "C" to the beginning of the block, it should go before the
357 // DbgVariableRecords. They'll stay on "D".
358 CInst->moveBefore(BB, BB.begin());
359 EXPECT_TRUE(!CInst->DebugMarker ||
360 CInst->DebugMarker->StoredDbgRecords.empty());
361 EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty());
362 EXPECT_EQ(&*BB.begin(), CInst);
363 EXPECT_EQ(CInst->getNextNode(), DInst);
365 // Move back.
366 CInst->moveBefore(BInst);
367 EXPECT_EQ(&*BB.begin(), DInst);
369 // Current order of insts: "D -> C -> B -> Ret". DbgVariableRecords on "D".
370 // Now move CInst to the position of DInst, but using getIterator instead of
371 // BasicBlock::begin. This signals that we want the "C" instruction to be
372 // immediately before "D", with any DbgVariableRecords on "D" now moving to
373 // "C". It's the equivalent of moving an instruction to the position between a
374 // run of dbg.values and the next instruction.
375 CInst->moveBefore(BB, DInst->getIterator());
376 // CInst gains the DbgVariableRecords.
377 EXPECT_TRUE(!DInst->DebugMarker ||
378 DInst->DebugMarker->StoredDbgRecords.empty());
379 EXPECT_FALSE(CInst->DebugMarker->StoredDbgRecords.empty());
380 EXPECT_EQ(&*BB.begin(), CInst);
383 TEST(BasicBlockDbgInfoTest, InstrDbgAccess) {
384 LLVMContext C;
385 std::unique_ptr<Module> M = parseIR(C, R"(
386 define i16 @f(i16 %a) !dbg !6 {
387 %b = add i16 %a, 1, !dbg !11
388 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
389 %c = add i16 %a, 1, !dbg !11
390 %d = add i16 %a, 1, !dbg !11
391 ret i16 0, !dbg !11
393 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
394 attributes #0 = { nounwind readnone speculatable willreturn }
396 !llvm.dbg.cu = !{!0}
397 !llvm.module.flags = !{!5}
399 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
400 !1 = !DIFile(filename: "t.ll", directory: "/")
401 !2 = !{}
402 !5 = !{i32 2, !"Debug Info Version", i32 3}
403 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
404 !7 = !DISubroutineType(types: !2)
405 !8 = !{!9}
406 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
407 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
408 !11 = !DILocation(line: 1, column: 1, scope: !6)
409 )");
411 // Check that DbgVariableRecords can be accessed from Instructions without
412 // digging into the depths of DbgMarkers.
413 BasicBlock &BB = M->getFunction("f")->getEntryBlock();
415 Instruction *BInst = &*BB.begin();
416 Instruction *CInst = BInst->getNextNode();
417 Instruction *DInst = CInst->getNextNode();
419 ASSERT_FALSE(BInst->DebugMarker);
420 ASSERT_TRUE(CInst->DebugMarker);
421 ASSERT_EQ(CInst->DebugMarker->StoredDbgRecords.size(), 1u);
422 DbgRecord *DVR1 = &*CInst->DebugMarker->StoredDbgRecords.begin();
423 ASSERT_TRUE(DVR1);
424 EXPECT_FALSE(BInst->hasDbgRecords());
426 // Clone DbgVariableRecords from one inst to another. Other arguments to clone
427 // are tested in DbgMarker test.
428 auto Range1 = BInst->cloneDebugInfoFrom(CInst);
429 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u);
430 DbgRecord *DVR2 = &*BInst->DebugMarker->StoredDbgRecords.begin();
431 EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), 1u);
432 EXPECT_EQ(&*Range1.begin(), DVR2);
433 EXPECT_NE(DVR1, DVR2);
435 // We should be able to get a range over exactly the same information.
436 auto Range2 = BInst->getDbgRecordRange();
437 EXPECT_EQ(Range1.begin(), Range2.begin());
438 EXPECT_EQ(Range1.end(), Range2.end());
440 // We should be able to query if there are DbgVariableRecords,
441 EXPECT_TRUE(BInst->hasDbgRecords());
442 EXPECT_TRUE(CInst->hasDbgRecords());
443 EXPECT_FALSE(DInst->hasDbgRecords());
445 // Dropping should be easy,
446 BInst->dropDbgRecords();
447 EXPECT_FALSE(BInst->hasDbgRecords());
448 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 0u);
450 // And we should be able to drop individual DbgVariableRecords.
451 CInst->dropOneDbgRecord(DVR1);
452 EXPECT_FALSE(CInst->hasDbgRecords());
453 EXPECT_EQ(CInst->DebugMarker->StoredDbgRecords.size(), 0u);
456 /* Let's recall the big illustration from BasicBlock::spliceDebugInfo:
458 Dest
460 this-block: A----A----A ====A----A----A----A---A---A
461 Src-block ++++B---B---B---B:::C
463 First Last
465 in all it's glory. Depending on the bit-configurations for the iterator head
466 / tail bits on the three named iterators, there are eight ways for a splice to
467 occur. To save the amount of thinking needed to pack this into one unit test,
468 just test the same IR eight times with difference splices. The IR shall be
469 thus:
471 define i16 @f(i16 %a) !dbg !6 {
472 entry:
473 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
474 %b = add i16 %a, 1, !dbg !11
475 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
476 br label %exit, !dbg !11
478 exit:
479 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
480 %c = add i16 %b, 1, !dbg !11
481 ret i16 0, !dbg !11
484 The iterators will be:
485 Dest: exit block, "c" instruction.
486 First: entry block, "b" instruction.
487 Last: entry block, branch instruction.
489 The numbered configurations will be:
491 | Dest-Head | First-Head | Last-tail
492 ----+----------------+----------------+------------
493 0 | false | false | false
494 1 | true | false | false
495 2 | false | true | false
496 3 | true | true | false
497 4 | false | false | true
498 5 | true | false | true
499 6 | false | true | true
500 7 | true | true | true
502 Each numbered test scenario will also have a short explanation indicating what
503 this bit configuration represents.
506 static const std::string SpliceTestIR = R"(
507 define i16 @f(i16 %a) !dbg !6 {
508 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
509 %b = add i16 %a, 1, !dbg !11
510 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
511 br label %exit, !dbg !11
513 exit:
514 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
515 %c = add i16 %b, 1, !dbg !11
516 ret i16 0, !dbg !11
518 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
519 attributes #0 = { nounwind readnone speculatable willreturn }
521 !llvm.dbg.cu = !{!0}
522 !llvm.module.flags = !{!5}
524 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
525 !1 = !DIFile(filename: "t.ll", directory: "/")
526 !2 = !{}
527 !5 = !{i32 2, !"Debug Info Version", i32 3}
528 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
529 !7 = !DISubroutineType(types: !2)
530 !8 = !{!9}
531 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
532 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
533 !11 = !DILocation(line: 1, column: 1, scope: !6)
536 class DbgSpliceTest : public ::testing::Test {
537 protected:
538 LLVMContext C;
539 std::unique_ptr<Module> M;
540 BasicBlock *BBEntry, *BBExit;
541 BasicBlock::iterator Dest, First, Last;
542 Instruction *BInst, *Branch, *CInst;
543 DbgVariableRecord *DVRA, *DVRB, *DVRConst;
545 void SetUp() override {
546 M = parseIR(C, SpliceTestIR.c_str());
548 BBEntry = &M->getFunction("f")->getEntryBlock();
549 BBExit = BBEntry->getNextNode();
551 Dest = BBExit->begin();
552 First = BBEntry->begin();
553 Last = BBEntry->getTerminator()->getIterator();
554 BInst = &*First;
555 Branch = &*Last;
556 CInst = &*Dest;
558 DVRA =
559 cast<DbgVariableRecord>(&*BInst->DebugMarker->StoredDbgRecords.begin());
560 DVRB = cast<DbgVariableRecord>(
561 &*Branch->DebugMarker->StoredDbgRecords.begin());
562 DVRConst =
563 cast<DbgVariableRecord>(&*CInst->DebugMarker->StoredDbgRecords.begin());
566 bool InstContainsDbgVariableRecord(Instruction *I, DbgVariableRecord *DVR) {
567 for (DbgRecord &D : I->getDbgRecordRange()) {
568 if (&D == DVR) {
569 // Confirm too that the links between the records are correct.
570 EXPECT_EQ(DVR->Marker, I->DebugMarker);
571 EXPECT_EQ(I->DebugMarker->MarkedInstr, I);
572 return true;
575 return false;
578 bool CheckDVROrder(Instruction *I,
579 SmallVector<DbgVariableRecord *> CheckVals) {
580 SmallVector<DbgRecord *> Vals;
581 for (DbgRecord &D : I->getDbgRecordRange())
582 Vals.push_back(&D);
584 EXPECT_EQ(Vals.size(), CheckVals.size());
585 if (Vals.size() != CheckVals.size())
586 return false;
588 for (unsigned int I = 0; I < Vals.size(); ++I) {
589 EXPECT_EQ(Vals[I], CheckVals[I]);
590 // Provide another expectation failure to let us localise what goes wrong,
591 // by returning a flag to the caller.
592 if (Vals[I] != CheckVals[I])
593 return false;
595 return true;
599 TEST_F(DbgSpliceTest, DbgSpliceTest0) {
600 Dest.setHeadBit(false);
601 First.setHeadBit(false);
602 Last.setTailBit(false);
605 define i16 @f(i16 %a) !dbg !6 {
606 BBEntry entry:
607 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
608 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
609 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
610 !dbg !11 Last br label %exit, !dbg !11
612 BBExit exit:
613 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
614 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
615 !dbg !11
618 Splice from First, not including leading dbg.value, to Last, including the
619 trailing dbg.value. Place at Dest, between the constant dbg.value and %c.
620 %b, and the following dbg.value, should move, to:
622 define i16 @f(i16 %a) !dbg !6 {
623 BBEntry entry:
624 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
625 !DIExpression()), !dbg !11 Last br label %exit, !dbg !11
627 BBExit exit:
628 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
629 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
630 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
631 !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11
636 BBExit->splice(Dest, BBEntry, First, Last);
637 EXPECT_EQ(BInst->getParent(), BBExit);
638 EXPECT_EQ(CInst->getParent(), BBExit);
639 EXPECT_EQ(Branch->getParent(), BBEntry);
641 // DVRB: should be on Dest, in exit block.
642 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB));
644 // DVRA, should have "fallen" onto the branch, remained in entry block.
645 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA));
647 // DVRConst should be on the moved %b instruction.
648 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst));
651 TEST_F(DbgSpliceTest, DbgSpliceTest1) {
652 Dest.setHeadBit(true);
653 First.setHeadBit(false);
654 Last.setTailBit(false);
657 define i16 @f(i16 %a) !dbg !6 {
658 BBEntry entry:
659 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
660 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
661 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
662 !dbg !11 Last br label %exit, !dbg !11
664 BBExit exit:
665 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
666 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
667 !dbg !11
670 Splice from First, not including leading dbg.value, to Last, including the
671 trailing dbg.value. Place at the head of Dest, i.e. at the very start of
672 BBExit, before any debug-info there. Becomes:
674 define i16 @f(i16 %a) !dbg !6 {
675 BBEntry entry:
676 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
677 !DIExpression()), !dbg !11 Last br label %exit, !dbg !11
679 BBExit exit:
680 First %b = add i16 %a, 1, !dbg !11
681 DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
682 !DIExpression()), !dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0,
683 metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1,
684 !dbg !11 ret i16 0, !dbg !11
689 BBExit->splice(Dest, BBEntry, First, Last);
690 EXPECT_EQ(BInst->getParent(), BBExit);
691 EXPECT_EQ(CInst->getParent(), BBExit);
692 EXPECT_EQ(Branch->getParent(), BBEntry);
694 // DVRB: should be on CInst, in exit block.
695 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB));
697 // DVRA, should have "fallen" onto the branch, remained in entry block.
698 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA));
700 // DVRConst should be behind / after the moved instructions, remain on CInst.
701 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
703 // Order of DVRB and DVRConst should be thus:
704 EXPECT_TRUE(CheckDVROrder(CInst, {DVRB, DVRConst}));
707 TEST_F(DbgSpliceTest, DbgSpliceTest2) {
708 Dest.setHeadBit(false);
709 First.setHeadBit(true);
710 Last.setTailBit(false);
713 define i16 @f(i16 %a) !dbg !6 {
714 BBEntry entry:
715 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
716 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
717 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
718 !dbg !11 Last br label %exit, !dbg !11
720 BBExit exit:
721 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
722 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
723 !dbg !11
726 Splice from head of First, which includes the leading dbg.value, to Last,
727 including the trailing dbg.value. Place in front of Dest, but after any
728 debug-info there. Becomes:
730 define i16 @f(i16 %a) !dbg !6 {
731 BBEntry entry:
732 Last br label %exit, !dbg !11
734 BBExit exit:
735 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
736 !DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a,
737 metadata !9, metadata !DIExpression()), !dbg !11 First %b = add i16 %a, 1,
738 !dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9,
739 metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret
740 i16 0, !dbg !11
745 BBExit->splice(Dest, BBEntry, First, Last);
746 EXPECT_EQ(BInst->getParent(), BBExit);
747 EXPECT_EQ(CInst->getParent(), BBExit);
749 // DVRB: should be on CInst, in exit block.
750 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB));
752 // DVRA, should have transferred with the spliced instructions, remains on
753 // the "b" inst.
754 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA));
756 // DVRConst should be ahead of the moved instructions, ahead of BInst.
757 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst));
759 // Order of DVRA and DVRConst should be thus:
760 EXPECT_TRUE(CheckDVROrder(BInst, {DVRConst, DVRA}));
763 TEST_F(DbgSpliceTest, DbgSpliceTest3) {
764 Dest.setHeadBit(true);
765 First.setHeadBit(true);
766 Last.setTailBit(false);
769 define i16 @f(i16 %a) !dbg !6 {
770 BBEntry entry:
771 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
772 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
773 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
774 !dbg !11 Last br label %exit, !dbg !11
776 BBExit exit:
777 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
778 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
779 !dbg !11
782 Splice from head of First, which includes the leading dbg.value, to Last,
783 including the trailing dbg.value. Place at head of Dest, before any
784 debug-info there. Becomes:
786 define i16 @f(i16 %a) !dbg !6 {
787 BBEntry entry:
788 Last br label %exit, !dbg !11
790 BBExit exit:
791 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
792 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
793 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
794 !dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9,
795 metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret
796 i16 0, !dbg !11
800 BBExit->splice(Dest, BBEntry, First, Last);
801 EXPECT_EQ(BInst->getParent(), BBExit);
802 EXPECT_EQ(CInst->getParent(), BBExit);
804 // DVRB: should be on CInst, in exit block.
805 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB));
807 // DVRA, should have transferred with the spliced instructions, remains on
808 // the "b" inst.
809 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA));
811 // DVRConst should be behind the moved instructions, ahead of CInst.
812 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
814 // Order of DVRB and DVRConst should be thus:
815 EXPECT_TRUE(CheckDVROrder(CInst, {DVRB, DVRConst}));
818 TEST_F(DbgSpliceTest, DbgSpliceTest4) {
819 Dest.setHeadBit(false);
820 First.setHeadBit(false);
821 Last.setTailBit(true);
824 define i16 @f(i16 %a) !dbg !6 {
825 BBEntry entry:
826 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
827 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
828 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
829 !dbg !11 Last br label %exit, !dbg !11
831 BBExit exit:
832 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
833 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
834 !dbg !11
837 Splice from First, not including the leading dbg.value, to Last, but NOT
838 including the trailing dbg.value because the tail bit is set. Place at Dest,
839 after any debug-info there. Becomes:
841 define i16 @f(i16 %a) !dbg !6 {
842 BBEntry entry:
843 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
844 !DIExpression()), !dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b,
845 metadata !9, metadata !DIExpression()), !dbg !11 Last br label %exit, !dbg
848 BBExit exit:
849 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
850 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 Dest %c =
851 add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11
855 BBExit->splice(Dest, BBEntry, First, Last);
856 EXPECT_EQ(BInst->getParent(), BBExit);
857 EXPECT_EQ(CInst->getParent(), BBExit);
858 EXPECT_EQ(Branch->getParent(), BBEntry);
860 // DVRB: should be on Branch as before, remain in entry block.
861 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
863 // DVRA, should have remained in entry block, falls onto Branch inst.
864 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA));
866 // DVRConst should be ahead of the moved instructions, BInst.
867 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst));
869 // Order of DVRA and DVRA should be thus:
870 EXPECT_TRUE(CheckDVROrder(Branch, {DVRA, DVRB}));
873 TEST_F(DbgSpliceTest, DbgSpliceTest5) {
874 Dest.setHeadBit(true);
875 First.setHeadBit(false);
876 Last.setTailBit(true);
879 define i16 @f(i16 %a) !dbg !6 {
880 BBEntry entry:
881 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
882 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
883 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
884 !dbg !11 Last br label %exit, !dbg !11
886 BBExit exit:
887 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
888 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
889 !dbg !11
892 Splice from First, not including the leading dbg.value, to Last, but NOT
893 including the trailing dbg.value because the tail bit is set. Place at head
894 of Dest, before any debug-info there. Becomes:
896 define i16 @f(i16 %a) !dbg !6 {
897 BBEntry entry:
898 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
899 !DIExpression()), !dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b,
900 metadata !9, metadata !DIExpression()), !dbg !11 Last br label %exit, !dbg
903 BBExit exit:
904 First %b = add i16 %a, 1, !dbg !11
905 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
906 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
907 !dbg !11
911 BBExit->splice(Dest, BBEntry, First, Last);
912 EXPECT_EQ(BInst->getParent(), BBExit);
913 EXPECT_EQ(CInst->getParent(), BBExit);
914 EXPECT_EQ(Branch->getParent(), BBEntry);
916 // DVRB: should be on Branch as before, remain in entry block.
917 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
919 // DVRA, should have remained in entry block, falls onto Branch inst.
920 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA));
922 // DVRConst should be behind of the moved instructions, on CInst.
923 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
925 // Order of DVRA and DVRB should be thus:
926 EXPECT_TRUE(CheckDVROrder(Branch, {DVRA, DVRB}));
929 TEST_F(DbgSpliceTest, DbgSpliceTest6) {
930 Dest.setHeadBit(false);
931 First.setHeadBit(true);
932 Last.setTailBit(true);
935 define i16 @f(i16 %a) !dbg !6 {
936 BBEntry entry:
937 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
938 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
939 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
940 !dbg !11 Last br label %exit, !dbg !11
942 BBExit exit:
943 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
944 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
945 !dbg !11
948 Splice from First, including the leading dbg.value, to Last, but NOT
949 including the trailing dbg.value because the tail bit is set. Place at Dest,
950 after any debug-info there. Becomes:
952 define i16 @f(i16 %a) !dbg !6 {
953 BBEntry entry:
954 DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
955 !DIExpression()), !dbg !11 Last br label %exit, !dbg !11
957 BBExit exit:
958 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
959 !DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a,
960 metadata !9, metadata !DIExpression()), !dbg !11 First %b = add i16 %a, 1,
961 !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11
965 BBExit->splice(Dest, BBEntry, First, Last);
966 EXPECT_EQ(BInst->getParent(), BBExit);
967 EXPECT_EQ(CInst->getParent(), BBExit);
968 EXPECT_EQ(Branch->getParent(), BBEntry);
970 // DVRB: should be on Branch as before, remain in entry block.
971 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
973 // DVRA, should have transferred to BBExit, on B inst.
974 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA));
976 // DVRConst should be ahead of the moved instructions, on BInst.
977 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst));
979 // Order of DVRA and DVRConst should be thus:
980 EXPECT_TRUE(CheckDVROrder(BInst, {DVRConst, DVRA}));
983 TEST_F(DbgSpliceTest, DbgSpliceTest7) {
984 Dest.setHeadBit(true);
985 First.setHeadBit(true);
986 Last.setTailBit(true);
989 define i16 @f(i16 %a) !dbg !6 {
990 BBEntry entry:
991 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
992 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
993 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
994 !dbg !11 Last br label %exit, !dbg !11
996 BBExit exit:
997 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
998 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
999 !dbg !11
1002 Splice from First, including the leading dbg.value, to Last, but NOT
1003 including the trailing dbg.value because the tail bit is set. Place at head
1004 of Dest, before any debug-info there. Becomes:
1006 define i16 @f(i16 %a) !dbg !6 {
1007 BBEntry entry:
1008 DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
1009 !DIExpression()), !dbg !11 Last br label %exit, !dbg !11
1011 BBExit exit:
1012 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
1013 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRConst call
1014 void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()),
1015 !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11
1019 BBExit->splice(Dest, BBEntry, First, Last);
1020 EXPECT_EQ(BInst->getParent(), BBExit);
1021 EXPECT_EQ(CInst->getParent(), BBExit);
1022 EXPECT_EQ(Branch->getParent(), BBEntry);
1024 // DVRB: should be on Branch as before, remain in entry block.
1025 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
1027 // DVRA, should have transferred to BBExit, on B inst.
1028 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA));
1030 // DVRConst should be after of the moved instructions, on CInst.
1031 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
1034 // But wait, there's more! What if you splice a range that is empty, but
1035 // implicitly contains debug-info? In the dbg.value design for debug-info,
1036 // this would be an explicit range, but in DbgVariableRecord debug-info, it
1037 // isn't. Check that if we try to do that, with differing head-bit values, that
1038 // DbgVariableRecords are transferred.
1039 // Test with empty transfers to Dest, with head bit set and not set.
1041 TEST_F(DbgSpliceTest, DbgSpliceEmpty0) {
1042 Dest.setHeadBit(false);
1043 First.setHeadBit(false);
1044 Last.setHeadBit(false);
1046 define i16 @f(i16 %a) !dbg !6 {
1047 BBEntry entry:
1048 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
1049 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
1050 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
1051 !dbg !11 Last br label %exit, !dbg !11
1053 BBExit exit:
1054 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
1055 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
1056 !dbg !11
1059 Splice from BBEntry.getFirstInsertionPt to First -- this implicitly is a
1060 splice of DVRA, but the iterators are pointing at the same instruction. The
1061 only difference is the setting of the head bit. Becomes;
1063 define i16 @f(i16 %a) !dbg !6 {
1064 First %b = add i16 %a, 1, !dbg !11
1065 DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
1066 !DIExpression()), !dbg !11 Last br label %exit, !dbg !11
1068 BBExit exit:
1069 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
1070 !DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a,
1071 metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1,
1072 !dbg !11 ret i16 0, !dbg !11
1076 BBExit->splice(Dest, BBEntry, BBEntry->getFirstInsertionPt(), First);
1077 EXPECT_EQ(BInst->getParent(), BBEntry);
1078 EXPECT_EQ(CInst->getParent(), BBExit);
1079 EXPECT_EQ(Branch->getParent(), BBEntry);
1081 // DVRB: should be on Branch as before, remain in entry block.
1082 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
1084 // DVRA, should have transferred to BBExit, on C inst.
1085 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRA));
1087 // DVRConst should be ahead of the moved DbgVariableRecord, on CInst.
1088 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
1090 // Order of DVRA and DVRConst should be thus:
1091 EXPECT_TRUE(CheckDVROrder(CInst, {DVRConst, DVRA}));
1094 TEST_F(DbgSpliceTest, DbgSpliceEmpty1) {
1095 Dest.setHeadBit(true);
1096 First.setHeadBit(false);
1097 Last.setHeadBit(false);
1099 define i16 @f(i16 %a) !dbg !6 {
1100 BBEntry entry:
1101 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
1102 !DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
1103 void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
1104 !dbg !11 Last br label %exit, !dbg !11
1106 BBExit exit:
1107 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
1108 !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
1109 !dbg !11
1112 Splice from BBEntry.getFirstInsertionPt to First -- this implicitly is a
1113 splice of DVRA, but the iterators are pointing at the same instruction. The
1114 only difference is the setting of the head bit. Insert at head of Dest,
1115 i.e. before DVRConst. Becomes;
1117 define i16 @f(i16 %a) !dbg !6 {
1118 First %b = add i16 %a, 1, !dbg !11
1119 DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
1120 !DIExpression()), !dbg !11 Last br label %exit, !dbg !11
1122 BBExit exit:
1123 DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
1124 !DIExpression()), !dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0,
1125 metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1,
1126 !dbg !11 ret i16 0, !dbg !11
1130 BBExit->splice(Dest, BBEntry, BBEntry->getFirstInsertionPt(), First);
1131 EXPECT_EQ(BInst->getParent(), BBEntry);
1132 EXPECT_EQ(CInst->getParent(), BBExit);
1133 EXPECT_EQ(Branch->getParent(), BBEntry);
1135 // DVRB: should be on Branch as before, remain in entry block.
1136 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
1138 // DVRA, should have transferred to BBExit, on C inst.
1139 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRA));
1141 // DVRConst should be ahead of the moved DbgVariableRecord, on CInst.
1142 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
1144 // Order of DVRA and DVRConst should be thus:
1145 EXPECT_TRUE(CheckDVROrder(CInst, {DVRA, DVRConst}));
1148 // If we splice new instructions into a block with trailing DbgVariableRecords,
1149 // then the trailing DbgVariableRecords should get flushed back out.
1150 TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) {
1151 LLVMContext C;
1152 std::unique_ptr<Module> M = parseIR(C, R"(
1153 define i16 @f(i16 %a) !dbg !6 {
1154 entry:
1155 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1156 br label %exit
1158 exit:
1159 %b = add i16 %a, 1, !dbg !11
1160 ret i16 0, !dbg !11
1162 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
1163 attributes #0 = { nounwind readnone speculatable willreturn }
1165 !llvm.dbg.cu = !{!0}
1166 !llvm.module.flags = !{!5}
1168 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1169 !1 = !DIFile(filename: "t.ll", directory: "/")
1170 !2 = !{}
1171 !5 = !{i32 2, !"Debug Info Version", i32 3}
1172 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1173 !7 = !DISubroutineType(types: !2)
1174 !8 = !{!9}
1175 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1176 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1177 !11 = !DILocation(line: 1, column: 1, scope: !6)
1178 )");
1180 BasicBlock &Entry = M->getFunction("f")->getEntryBlock();
1181 BasicBlock &Exit = *Entry.getNextNode();
1183 // Begin by forcing entry block to have dangling DbgVariableRecord.
1184 Entry.getTerminator()->eraseFromParent();
1185 ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr);
1186 EXPECT_TRUE(Entry.empty());
1188 // Now transfer the entire contents of the exit block into the entry.
1189 Entry.splice(Entry.end(), &Exit, Exit.begin(), Exit.end());
1191 // The trailing DbgVariableRecord should have been placed at the front of
1192 // what's been spliced in.
1193 Instruction *BInst = &*Entry.begin();
1194 ASSERT_TRUE(BInst->DebugMarker);
1195 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u);
1198 // When we remove instructions from the program, adjacent DbgVariableRecords
1199 // coalesce together into one DbgMarker. In "old" dbg.value mode you could
1200 // re-insert the removed instruction back into the middle of a sequence of
1201 // dbg.values. Test that this can be replicated correctly by DbgVariableRecords
1202 TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) {
1203 LLVMContext C;
1204 std::unique_ptr<Module> M = parseIR(C, R"(
1205 define i16 @f(i16 %a) !dbg !6 {
1206 entry:
1207 %qux = sub i16 %a, 0
1208 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1209 %foo = add i16 %a, %a
1210 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
1211 ret i16 1
1213 declare void @llvm.dbg.value(metadata, metadata, metadata)
1215 !llvm.dbg.cu = !{!0}
1216 !llvm.module.flags = !{!5}
1218 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1219 !1 = !DIFile(filename: "t.ll", directory: "/")
1220 !2 = !{}
1221 !5 = !{i32 2, !"Debug Info Version", i32 3}
1222 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1223 !7 = !DISubroutineType(types: !2)
1224 !8 = !{!9}
1225 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1226 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1227 !11 = !DILocation(line: 1, column: 1, scope: !6)
1228 )");
1230 BasicBlock &Entry = M->getFunction("f")->getEntryBlock();
1232 // Fetch the relevant instructions from the converted function.
1233 Instruction *SubInst = &*Entry.begin();
1234 ASSERT_TRUE(isa<BinaryOperator>(SubInst));
1235 Instruction *AddInst = SubInst->getNextNode();
1236 ASSERT_TRUE(isa<BinaryOperator>(AddInst));
1237 Instruction *RetInst = AddInst->getNextNode();
1238 ASSERT_TRUE(isa<ReturnInst>(RetInst));
1240 // add and sub should both have one DbgVariableRecord on add and ret.
1241 EXPECT_FALSE(SubInst->hasDbgRecords());
1242 EXPECT_TRUE(AddInst->hasDbgRecords());
1243 EXPECT_TRUE(RetInst->hasDbgRecords());
1244 auto R1 = AddInst->getDbgRecordRange();
1245 EXPECT_EQ(std::distance(R1.begin(), R1.end()), 1u);
1246 auto R2 = RetInst->getDbgRecordRange();
1247 EXPECT_EQ(std::distance(R2.begin(), R2.end()), 1u);
1249 // The Supported (TM) code sequence for removing then reinserting insts
1250 // after another instruction:
1251 std::optional<DbgVariableRecord::self_iterator> Pos =
1252 AddInst->getDbgReinsertionPosition();
1253 AddInst->removeFromParent();
1255 // We should have a re-insertion position.
1256 ASSERT_TRUE(Pos);
1257 // Both DbgVariableRecords should now be attached to the ret inst.
1258 auto R3 = RetInst->getDbgRecordRange();
1259 EXPECT_EQ(std::distance(R3.begin(), R3.end()), 2u);
1261 // Re-insert and re-insert.
1262 AddInst->insertAfter(SubInst);
1263 Entry.reinsertInstInDbgRecords(AddInst, Pos);
1264 // We should be back into a position of having one DbgVariableRecord on add
1265 // and ret.
1266 EXPECT_FALSE(SubInst->hasDbgRecords());
1267 EXPECT_TRUE(AddInst->hasDbgRecords());
1268 EXPECT_TRUE(RetInst->hasDbgRecords());
1269 auto R4 = AddInst->getDbgRecordRange();
1270 EXPECT_EQ(std::distance(R4.begin(), R4.end()), 1u);
1271 auto R5 = RetInst->getDbgRecordRange();
1272 EXPECT_EQ(std::distance(R5.begin(), R5.end()), 1u);
1275 // Test instruction removal and re-insertion, this time with one
1276 // DbgVariableRecord that should hop up one instruction.
1277 TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDbgVariableRecord) {
1278 LLVMContext C;
1279 std::unique_ptr<Module> M = parseIR(C, R"(
1280 define i16 @f(i16 %a) !dbg !6 {
1281 entry:
1282 %qux = sub i16 %a, 0
1283 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1284 %foo = add i16 %a, %a
1285 ret i16 1
1287 declare void @llvm.dbg.value(metadata, metadata, metadata)
1289 !llvm.dbg.cu = !{!0}
1290 !llvm.module.flags = !{!5}
1292 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1293 !1 = !DIFile(filename: "t.ll", directory: "/")
1294 !2 = !{}
1295 !5 = !{i32 2, !"Debug Info Version", i32 3}
1296 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1297 !7 = !DISubroutineType(types: !2)
1298 !8 = !{!9}
1299 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1300 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1301 !11 = !DILocation(line: 1, column: 1, scope: !6)
1302 )");
1304 BasicBlock &Entry = M->getFunction("f")->getEntryBlock();
1306 // Fetch the relevant instructions from the converted function.
1307 Instruction *SubInst = &*Entry.begin();
1308 ASSERT_TRUE(isa<BinaryOperator>(SubInst));
1309 Instruction *AddInst = SubInst->getNextNode();
1310 ASSERT_TRUE(isa<BinaryOperator>(AddInst));
1311 Instruction *RetInst = AddInst->getNextNode();
1312 ASSERT_TRUE(isa<ReturnInst>(RetInst));
1314 // There should be one DbgVariableRecord.
1315 EXPECT_FALSE(SubInst->hasDbgRecords());
1316 EXPECT_TRUE(AddInst->hasDbgRecords());
1317 EXPECT_FALSE(RetInst->hasDbgRecords());
1318 auto R1 = AddInst->getDbgRecordRange();
1319 EXPECT_EQ(std::distance(R1.begin(), R1.end()), 1u);
1321 // The Supported (TM) code sequence for removing then reinserting insts:
1322 std::optional<DbgVariableRecord::self_iterator> Pos =
1323 AddInst->getDbgReinsertionPosition();
1324 AddInst->removeFromParent();
1326 // No re-insertion position as there were no DbgVariableRecords on the ret.
1327 ASSERT_FALSE(Pos);
1328 // The single DbgVariableRecord should now be attached to the ret inst.
1329 EXPECT_TRUE(RetInst->hasDbgRecords());
1330 auto R2 = RetInst->getDbgRecordRange();
1331 EXPECT_EQ(std::distance(R2.begin(), R2.end()), 1u);
1333 // Re-insert and re-insert.
1334 AddInst->insertAfter(SubInst);
1335 Entry.reinsertInstInDbgRecords(AddInst, Pos);
1336 // We should be back into a position of having one DbgVariableRecord on the
1337 // AddInst.
1338 EXPECT_FALSE(SubInst->hasDbgRecords());
1339 EXPECT_TRUE(AddInst->hasDbgRecords());
1340 EXPECT_FALSE(RetInst->hasDbgRecords());
1341 auto R3 = AddInst->getDbgRecordRange();
1342 EXPECT_EQ(std::distance(R3.begin(), R3.end()), 1u);
1345 // Similar to the above, what if we splice into an empty block with debug-info,
1346 // with debug-info at the start of the moving range, that we intend to be
1347 // transferred. The dbg.value of %a should remain at the start, but come ahead
1348 // of the i16 0 dbg.value.
1349 TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) {
1350 LLVMContext C;
1351 std::unique_ptr<Module> M = parseIR(C, R"(
1352 define i16 @f(i16 %a) !dbg !6 {
1353 entry:
1354 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1355 br label %exit
1357 exit:
1358 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
1359 %b = add i16 %a, 1, !dbg !11
1360 call void @llvm.dbg.value(metadata i16 1, metadata !9, metadata !DIExpression()), !dbg !11
1361 ret i16 0, !dbg !11
1363 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
1364 attributes #0 = { nounwind readnone speculatable willreturn }
1366 !llvm.dbg.cu = !{!0}
1367 !llvm.module.flags = !{!5}
1369 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1370 !1 = !DIFile(filename: "t.ll", directory: "/")
1371 !2 = !{}
1372 !5 = !{i32 2, !"Debug Info Version", i32 3}
1373 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1374 !7 = !DISubroutineType(types: !2)
1375 !8 = !{!9}
1376 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1377 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1378 !11 = !DILocation(line: 1, column: 1, scope: !6)
1379 )");
1381 Function &F = *M->getFunction("f");
1382 BasicBlock &Entry = F.getEntryBlock();
1383 BasicBlock &Exit = *Entry.getNextNode();
1385 // Begin by forcing entry block to have dangling DbgVariableRecord.
1386 Entry.getTerminator()->eraseFromParent();
1387 ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr);
1388 EXPECT_TRUE(Entry.empty());
1390 // Now transfer the entire contents of the exit block into the entry. This
1391 // includes both dbg.values.
1392 Entry.splice(Entry.end(), &Exit, Exit.begin(), Exit.end());
1394 // We should now have two dbg.values on the first instruction, and they
1395 // should be in the correct order of %a, then 0.
1396 Instruction *BInst = &*Entry.begin();
1397 ASSERT_TRUE(BInst->hasDbgRecords());
1398 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 2u);
1399 SmallVector<DbgVariableRecord *, 2> DbgVariableRecords;
1400 for (DbgRecord &DVR : BInst->getDbgRecordRange())
1401 DbgVariableRecords.push_back(cast<DbgVariableRecord>(&DVR));
1403 EXPECT_EQ(DbgVariableRecords[0]->getVariableLocationOp(0), F.getArg(0));
1404 Value *SecondDVRValue = DbgVariableRecords[1]->getVariableLocationOp(0);
1405 ASSERT_TRUE(isa<ConstantInt>(SecondDVRValue));
1406 EXPECT_EQ(cast<ConstantInt>(SecondDVRValue)->getZExtValue(), 0ull);
1408 // No trailing DbgVariableRecords in the entry block now.
1409 EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr);
1412 // Similar test again, but this time: splice the contents of exit into entry,
1413 // with the intention of leaving the first dbg.value (i16 0) behind.
1414 TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) {
1415 LLVMContext C;
1416 std::unique_ptr<Module> M = parseIR(C, R"(
1417 define i16 @f(i16 %a) !dbg !6 {
1418 entry:
1419 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1420 br label %exit
1422 exit:
1423 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
1424 %b = add i16 %a, 1, !dbg !11
1425 call void @llvm.dbg.value(metadata i16 1, metadata !9, metadata !DIExpression()), !dbg !11
1426 ret i16 0, !dbg !11
1428 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
1429 attributes #0 = { nounwind readnone speculatable willreturn }
1431 !llvm.dbg.cu = !{!0}
1432 !llvm.module.flags = !{!5}
1434 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1435 !1 = !DIFile(filename: "t.ll", directory: "/")
1436 !2 = !{}
1437 !5 = !{i32 2, !"Debug Info Version", i32 3}
1438 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1439 !7 = !DISubroutineType(types: !2)
1440 !8 = !{!9}
1441 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1442 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1443 !11 = !DILocation(line: 1, column: 1, scope: !6)
1444 )");
1446 Function &F = *M->getFunction("f");
1447 BasicBlock &Entry = F.getEntryBlock();
1448 BasicBlock &Exit = *Entry.getNextNode();
1450 // Begin by forcing entry block to have dangling DbgVariableRecord.
1451 Entry.getTerminator()->eraseFromParent();
1452 ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr);
1453 EXPECT_TRUE(Entry.empty());
1455 // Now transfer into the entry block -- fetching the first instruction with
1456 // begin and then calling getIterator clears the "head" bit, meaning that the
1457 // range to move will not include any leading DbgVariableRecords.
1458 Entry.splice(Entry.end(), &Exit, Exit.begin()->getIterator(), Exit.end());
1460 // We should now have one dbg.values on the first instruction, %a.
1461 Instruction *BInst = &*Entry.begin();
1462 ASSERT_TRUE(BInst->hasDbgRecords());
1463 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u);
1464 SmallVector<DbgVariableRecord *, 2> DbgVariableRecords;
1465 for (DbgRecord &DVR : BInst->getDbgRecordRange())
1466 DbgVariableRecords.push_back(cast<DbgVariableRecord>(&DVR));
1468 EXPECT_EQ(DbgVariableRecords[0]->getVariableLocationOp(0), F.getArg(0));
1469 // No trailing DbgVariableRecords in the entry block now.
1470 EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr);
1472 // We should have nothing left in the exit block...
1473 EXPECT_TRUE(Exit.empty());
1474 // ... except for some dangling DbgVariableRecords.
1475 EXPECT_NE(Exit.getTrailingDbgRecords(), nullptr);
1476 EXPECT_FALSE(Exit.getTrailingDbgRecords()->empty());
1477 Exit.getTrailingDbgRecords()->eraseFromParent();
1478 Exit.deleteTrailingDbgRecords();
1481 // What if we moveBefore end() -- there might be no debug-info there, in which
1482 // case we shouldn't crash.
1483 TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) {
1484 LLVMContext C;
1485 std::unique_ptr<Module> M = parseIR(C, R"(
1486 define i16 @f(i16 %a) !dbg !6 {
1487 entry:
1488 br label %exit
1490 exit:
1491 ret i16 0, !dbg !11
1493 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
1494 attributes #0 = { nounwind readnone speculatable willreturn }
1496 !llvm.dbg.cu = !{!0}
1497 !llvm.module.flags = !{!5}
1499 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1500 !1 = !DIFile(filename: "t.ll", directory: "/")
1501 !2 = !{}
1502 !5 = !{i32 2, !"Debug Info Version", i32 3}
1503 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1504 !7 = !DISubroutineType(types: !2)
1505 !8 = !{!9}
1506 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1507 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1508 !11 = !DILocation(line: 1, column: 1, scope: !6)
1509 )");
1511 Function &F = *M->getFunction("f");
1512 BasicBlock &Entry = F.getEntryBlock();
1513 BasicBlock &Exit = *Entry.getNextNode();
1515 // Move the return to the end of the entry block.
1516 Instruction *Br = Entry.getTerminator();
1517 Instruction *Ret = Exit.getTerminator();
1518 EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr);
1519 Ret->moveBefore(Entry, Entry.end());
1520 Br->eraseFromParent();
1522 // There should continue to not be any debug-info anywhere.
1523 EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr);
1524 EXPECT_EQ(Exit.getTrailingDbgRecords(), nullptr);
1525 EXPECT_FALSE(Ret->hasDbgRecords());
1528 } // End anonymous namespace.