Index: llvm/trunk/lib/IR/DebugInfo.cpp =================================================================== --- llvm/trunk/lib/IR/DebugInfo.cpp +++ llvm/trunk/lib/IR/DebugInfo.cpp @@ -79,9 +79,19 @@ processScope(M->getScope()); } } - for (auto &F : M.functions()) + for (auto &F : M.functions()) { if (auto *SP = cast_or_null(F.getSubprogram())) processSubprogram(SP); + // There could be subprograms from inlined functions referenced from + // instructions only. Walk the function to find them. + for (const BasicBlock &BB : F) { + for (const Instruction &I : BB) { + if (!I.getDebugLoc()) + continue; + processLocation(M, I.getDebugLoc().get()); + } + } + } } void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) { Index: llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp +++ llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp @@ -324,10 +324,9 @@ } std::set LiveCUs; - // Any CU referenced from a function is live. - for (Function &F : M.functions()) { - DISubprogram *SP = F.getSubprogram(); - if (SP && SP->getUnit()) + // Any CU referenced from a subprogram is live. + for (DISubprogram *SP : F.subprograms()) { + if (SP->getUnit()) LiveCUs.insert(SP->getUnit()); } Index: llvm/trunk/test/DebugInfo/Generic/debuginfofinder-inlined-cu.ll =================================================================== --- llvm/trunk/test/DebugInfo/Generic/debuginfofinder-inlined-cu.ll +++ llvm/trunk/test/DebugInfo/Generic/debuginfofinder-inlined-cu.ll @@ -0,0 +1,31 @@ +; RUN: opt -analyze -module-debuginfo < %s | FileCheck %s + +; Verify that both compile units, even though one compile units's functions +; were entirely inlined into the other. +;CHECK: Compile unit: DW_LANG_C99 from /tmp/test1.c +;CHECK: Compile unit: DW_LANG_C99 from /tmp/test2.c +;CHECK: Subprogram: f from /tmp/test1.c:1 +;CHECK: Subprogram: g from /tmp/test2.c:1 + +define void @f() !dbg !4 { + ret void, !dbg !15 +} + +!llvm.dbg.cu = !{!0, !8} +!llvm.module.flags = !{!13, !16} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.4 (192092)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!1 = !DIFile(filename: "test1.c", directory: "/tmp") +!2 = !{} +!4 = distinct !DISubprogram(name: "f", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, variables: !2) +!5 = !DIFile(filename: "test1.c", directory: "/tmp") +!6 = !DISubroutineType(types: !7) +!7 = !{null} +!8 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.4 (192092)", isOptimized: false, emissionKind: FullDebug, file: !9, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!9 = !DIFile(filename: "test2.c", directory: "/tmp") +!11 = distinct !DISubprogram(name: "g", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !8, scopeLine: 1, file: !9, scope: !12, type: !6, variables: !2) +!12 = !DIFile(filename: "test2.c", directory: "/tmp") +!13 = !{i32 2, !"Dwarf Version", i32 4} +!14 = !DILocation(line: 1, scope: !4) +!15 = !DILocation(line: 1, scope: !11, inlinedAt: !14) +!16 = !{i32 1, !"Debug Info Version", i32 3} Index: llvm/trunk/test/Transforms/StripSymbols/strip-dead-debug-info.ll =================================================================== --- llvm/trunk/test/Transforms/StripSymbols/strip-dead-debug-info.ll +++ llvm/trunk/test/Transforms/StripSymbols/strip-dead-debug-info.ll @@ -24,7 +24,7 @@ define i32 @foo(i32 %i) #2 !dbg !15 { entry: tail call void @llvm.dbg.value(metadata i32 %i, i64 0, metadata !18, metadata !19), !dbg !20 - %.0 = load i32, i32* @xyz, align 4 + %.0 = load i32, i32* @xyz, align 4, !dbg !30 ret i32 %.0, !dbg !21 } @@ -32,7 +32,7 @@ attributes #1 = { nounwind readnone ssp } attributes #2 = { nounwind readonly ssp } -!llvm.dbg.cu = !{!4, !23, !24} +!llvm.dbg.cu = !{!4, !23, !24, !28} !llvm.module.flags = !{!9} !0 = !DIGlobalVariableExpression(var: !1) @@ -63,3 +63,6 @@ !25 = !{!26} !26 = !DIGlobalVariableExpression(var: !27, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)) !27 = !DIGlobalVariable(name: "abcd2", scope: !2, file: !2, line: 2, type: !3, isLocal: true, isDefinition: true) +!28 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "InlineTest", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !5) +!29 = distinct !DISubprogram(name: "inlinefunc", linkageName: "inlinefunc", scope: null, file: !2, line: 7, type: !16, isLocal: false, isDefinition: true, isOptimized: true, unit: !28) +!30 = !DILocation(line: 100, scope: !29, inlinedAt: !21)