diff options
-rw-r--r-- | llvm/lib/Linker/IRMover.cpp | 33 | ||||
-rw-r--r-- | llvm/test/Linker/thinlto_funcimport_debug.ll | 16 |
2 files changed, 40 insertions, 9 deletions
diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp index f30b623b523..6dbc183f782 100644 --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -501,6 +501,11 @@ class IRLinker { /// in an imported function. void findNeededSubprograms(); + /// Recursive helper for findNeededSubprograms to locate any DISubprogram + /// reached from the given Node, marking any found as needed. + void findReachedSubprograms(const MDNode *Node, + SmallPtrSet<const MDNode *, 16> &Visited); + /// The value mapper leaves nulls in the list of subprograms for any /// in the UnneededSubprograms map. Strip those out after metadata linking. void stripNullSubprograms(); @@ -1194,6 +1199,21 @@ bool IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) { return false; } +void IRLinker::findReachedSubprograms( + const MDNode *Node, SmallPtrSet<const MDNode *, 16> &Visited) { + if (!Visited.insert(Node).second) + return; + DISubprogram *SP = getDISubprogram(Node); + if (SP) + UnneededSubprograms.erase(SP); + for (auto &Op : Node->operands()) { + const MDNode *OpN = dyn_cast_or_null<MDNode>(Op.get()); + if (!OpN) + continue; + findReachedSubprograms(OpN, Visited); + } +} + void IRLinker::findNeededSubprograms() { // Track unneeded nodes to make it simpler to handle the case // where we are checking if an already-mapped SP is needed. @@ -1231,17 +1251,18 @@ void IRLinker::findNeededSubprograms() { if (!IsMetadataLinkingPostpass) return; // In the case of metadata linking as a postpass (e.g. for function - // importing), see which DISubprogram MD from the source has an associated - // temporary metadata node, which means the SP was needed by an imported - // function. + // importing), see which MD from the source has an associated + // temporary metadata node, which means that any DISubprogram + // reached from that MD was needed by an imported function. + SmallPtrSet<const MDNode *, 16> Visited; for (auto MDI : MetadataToIDs) { const MDNode *Node = dyn_cast<MDNode>(MDI.first); if (!Node) continue; - DISubprogram *SP = getDISubprogram(Node); - if (!SP || !ValIDToTempMDMap->count(MDI.second)) + if (!ValIDToTempMDMap->count(MDI.second)) continue; - UnneededSubprograms.erase(SP); + // Find any SP needed recursively from this needed Node. + findReachedSubprograms(Node, Visited); } } diff --git a/llvm/test/Linker/thinlto_funcimport_debug.ll b/llvm/test/Linker/thinlto_funcimport_debug.ll index 02f43b24c17..0e26a33375a 100644 --- a/llvm/test/Linker/thinlto_funcimport_debug.ll +++ b/llvm/test/Linker/thinlto_funcimport_debug.ll @@ -18,6 +18,8 @@ ; CHECK: distinct !DISubprogram(name: "func1" ; CHECK-NOT: distinct !DISubprogram(name: "func2" +; CHECK: distinct !DISubprogram(name: "func3" +; CHECK: distinct !DISubprogram(name: "func4" ; ModuleID = 'dbg.o' @@ -55,7 +57,7 @@ attributes #1 = { nounwind readnone } !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0 (trunk 251407) (llvm/trunk 251401)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3) !1 = !DIFile(filename: "dbg.c", directory: ".") !2 = !{} -!3 = !{!4, !11} +!3 = !{!4, !11, !27, !30} !4 = distinct !DISubprogram(name: "func1", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, variables: !8) !5 = !DISubroutineType(types: !6) !6 = !{!7, !7} @@ -72,9 +74,17 @@ attributes #1 = { nounwind readnone } !17 = !DIExpression() !18 = !DILocation(line: 1, column: 15, scope: !4) !19 = !DILocation(line: 2, column: 7, scope: !4) -!20 = !DILocation(line: 3, column: 9, scope: !21) -!21 = distinct !DILexicalBlock(scope: !4, file: !1, line: 3, column: 7) +!20 = !DILocation(line: 3, column: 9, scope: !21, inlinedAt: !26) +!21 = distinct !DILexicalBlock(scope: !27, file: !1, line: 3, column: 7) !22 = !DILocation(line: 3, column: 7, scope: !4) !23 = !DILocation(line: 5, column: 3, scope: !4) !24 = !DILocation(line: 8, column: 15, scope: !11) !25 = !DILocation(line: 9, column: 3, scope: !11) +!26 = !DILocation(line: 9, column: 3, scope: !4) +!27 = distinct !DISubprogram(name: "func3", scope: !1, file: !1, line: 8, type: !5, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, variables: !28) +!28 = !{!29} +!29 = !DILocalVariable(name: "n", arg: 1, scope: !30, file: !1, line: 8, type: !7) +!30 = distinct !DISubprogram(name: "func4", scope: !1, file: !1, line: 8, type: !5, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, variables: !31) +!31 = !{!32} +!32 = !DILocalVariable(name: "n", arg: 1, scope: !30, file: !1, line: 8, type: !7) + |