@@ -1525,4 +1525,103 @@ TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) {
15251525 EXPECT_FALSE (Ret->hasDbgRecords ());
15261526}
15271527
1528+ // This fails with an assert: "Assertion `!NodePtr->isKnownSentinel()' failed."
1529+ //
1530+ // Original C source:
1531+ //
1532+ // int foo(int fd) { return fd; }
1533+ // int (* arr[2])(int fd) = { foo };
1534+ // int bar(int id, int arg) {
1535+ // int ret = arr[id](arg);
1536+ // return ret;
1537+ // }
1538+ //
1539+ // Build command used: clang --target=armv7m-none-eabi -Oz -g -mcpu=cortex-m3 -mthumb -mabi=aapcs -c comm_reduce.c -emit-llvm
1540+ TEST (BasicBlockDbgInfoTest, DbgKnownSentinelCrash) {
1541+ LLVMContext C;
1542+ std::unique_ptr<Module> M = parseIR (C, R"---(
1543+ @arr = dso_local local_unnamed_addr global [2 x ptr] [ptr @foo, ptr null], align 4, !dbg !0
1544+
1545+ ; Function Attrs: minsize mustprogress nofree norecurse nosync nounwind optsize willreturn memory(none)
1546+ define dso_local noundef i32 @foo(i32 noundef returned %fd) #0 !dbg !19 {
1547+ entry:
1548+ #dbg_value(i32 %fd, !21, !DIExpression(), !22)
1549+ ret i32 %fd, !dbg !23
1550+ }
1551+
1552+ ; Function Attrs: minsize nounwind optsize
1553+ define dso_local i32 @bar(i32 noundef %id, i32 noundef %arg) local_unnamed_addr #1 !dbg !24 {
1554+ entry:
1555+ #dbg_value(i32 %id, !28, !DIExpression(), !31)
1556+ #dbg_value(i32 %arg, !29, !DIExpression(), !31)
1557+ %arrayidx = getelementptr inbounds [2 x ptr], ptr @arr, i32 0, i32 %id, !dbg !32
1558+ %0 = load ptr, ptr %arrayidx, align 4, !dbg !32, !tbaa !33
1559+ %call = tail call i32 %0(i32 noundef %arg) #2, !dbg !32
1560+ #dbg_value(i32 %call, !30, !DIExpression(), !31)
1561+ ret i32 %call, !dbg !37
1562+ }
1563+
1564+ attributes #0 = { minsize mustprogress nofree norecurse nosync nounwind optsize willreturn memory(none) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+armv7-m,+hwdiv,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
1565+ attributes #1 = { minsize nounwind optsize "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+armv7-m,+hwdiv,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
1566+ attributes #2 = { minsize nounwind optsize }
1567+
1568+ !llvm.dbg.cu = !{!2}
1569+ !llvm.module.flags = !{!12, !13, !14, !15, !16, !17}
1570+
1571+ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
1572+ !1 = distinct !DIGlobalVariable(name: "arr", scope: !2, file: !3, line: 3, type: !5, isLocal: false, isDefinition: true)
1573+ !2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
1574+ !3 = !DIFile(filename: "t.c", directory: "/")
1575+ !4 = !{!0}
1576+ !5 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 64, elements: !10)
1577+ !6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32)
1578+ !7 = !DISubroutineType(types: !8)
1579+ !8 = !{!9, !9}
1580+ !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
1581+ !10 = !{!11}
1582+ !11 = !DISubrange(count: 2)
1583+ !12 = !{i32 7, !"Dwarf Version", i32 5}
1584+ !13 = !{i32 2, !"Debug Info Version", i32 3}
1585+ !14 = !{i32 1, !"wchar_size", i32 4}
1586+ !15 = !{i32 1, !"min_enum_size", i32 4}
1587+ !16 = !{i32 7, !"frame-pointer", i32 2}
1588+ !17 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
1589+ !19 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 1, type: !7, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !20)
1590+ !20 = !{!21}
1591+ !21 = !DILocalVariable(name: "fd", arg: 1, scope: !19, file: !3, line: 1, type: !9)
1592+ !22 = !DILocation(line: 0, scope: !19)
1593+ !23 = !DILocation(line: 1, column: 19, scope: !19)
1594+ !24 = distinct !DISubprogram(name: "bar", scope: !3, file: !3, line: 5, type: !25, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !27)
1595+ !25 = !DISubroutineType(types: !26)
1596+ !26 = !{!9, !9, !9}
1597+ !27 = !{!28, !29, !30}
1598+ !28 = !DILocalVariable(name: "id", arg: 1, scope: !24, file: !3, line: 5, type: !9)
1599+ !29 = !DILocalVariable(name: "arg", arg: 2, scope: !24, file: !3, line: 5, type: !9)
1600+ !30 = !DILocalVariable(name: "ret", scope: !24, file: !3, line: 6, type: !9)
1601+ !31 = !DILocation(line: 0, scope: !24)
1602+ !32 = !DILocation(line: 6, column: 12, scope: !24)
1603+ !33 = !{!34, !34, i64 0}
1604+ !34 = !{!"any pointer", !35, i64 0}
1605+ !35 = !{!"omnipotent char", !36, i64 0}
1606+ !36 = !{!"Simple C/C++ TBAA"}
1607+ !37 = !DILocation(line: 7, column: 2, scope: !24)
1608+ )---" );
1609+ ASSERT_TRUE (M);
1610+
1611+ Function *F = M->getFunction (" bar" );
1612+ BasicBlock &BB = F->getEntryBlock ();
1613+
1614+ // Find %call
1615+ auto I = std::prev (BB.end (), 2 );
1616+
1617+ BasicBlock *NewBB = BasicBlock::Create (C, " NewBB" , F);
1618+ BasicBlock *NewBB2 = BasicBlock::Create (C, " NewBB2" , F);
1619+
1620+ NewBB->splice (NewBB->end (), &BB, std::next (I), BB.end ());
1621+ NewBB2->splice (NewBB2->end (), &BB, I, BB.end ());
1622+
1623+ llvm::dbgs () << " Didn't crash!\n " ;
1624+ ASSERT_TRUE (true );
1625+ }
1626+
15281627} // End anonymous namespace.
0 commit comments