diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -692,6 +692,7 @@ TempDIType clone() const { return TempDIType(cast(MDNode::clone().release())); } + bool ShareAcrossCUsOrderFree = true; unsigned getLine() const { return Line; } uint64_t getSizeInBits() const { return SizeInBits; } @@ -699,6 +700,13 @@ uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; } uint64_t getOffsetInBits() const { return OffsetInBits; } DIFlags getFlags() const { return Flags; } + bool isShareAcrossCUsOrderFree() const { return ShareAcrossCUsOrderFree; } + bool setShareAcrossCUsOrderNotFree() { + if (!ShareAcrossCUsOrderFree) + return false; + ShareAcrossCUsOrderFree = false; + return true; // changed + } DIScope *getScope() const { return cast_or_null(getRawScope()); } StringRef getName() const { return getStringOperand(2); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -26,12 +26,14 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolWasm.h" #include "llvm/MC/MachineLocation.h" +#include "llvm/Support/Casting.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" @@ -1096,8 +1098,18 @@ DIE *&AbsDef = getAbstractSPDies()[Scope->getScopeNode()]; if (AbsDef) return; - auto *SP = cast(Scope->getScopeNode()); + if (!DD->isSingleCU()) { + auto *Sc = dyn_cast(SP->getScope()); + while (Sc) { + if (auto *Ty = dyn_cast(Sc)) { + // Ty is not order free when share across CUs If has successor. + if (!Ty->setShareAcrossCUsOrderNotFree()) + break; + } + Sc = Sc->getScope(); + } + } DIE *ContextDIE; DwarfCompileUnit *ContextCU = this; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -752,6 +752,10 @@ return EnableOpConvert; } + bool isSingleCU() const { + return SingleCU; + } + bool shareAcrossDWOCUs() const; /// Returns the Dwarf Version. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -22,6 +22,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/Metadata.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -188,7 +189,7 @@ // together. if (isDwoUnit() && !DD->shareAcrossDWOCUs()) return false; - return (isa(D) || + return ((isa(D) && cast(D)->isShareAcrossCUsOrderFree()) || (isa(D) && !cast(D)->isDefinition())) && !DD->generateTypeUnits(); } diff --git a/llvm/test/DebugInfo/cross-cu-scope-2.ll b/llvm/test/DebugInfo/cross-cu-scope-2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/cross-cu-scope-2.ll @@ -0,0 +1,48 @@ +; RUN: %llc_dwarf %s -filetype=obj -o %t +; RUN: llvm-dwarfdump --debug-info %t | FileCheck %s +; RUN: llvm-dwarfdump --verify %t + +; CHECK: DW_TAG_compile_unit +; CHECK-NEXT: FooCU +; CHECK: DW_TAG_structure_type +; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_compile_unit +; CHECK-NEXT: MainCU + +define i64 @"$hashValueGetInFoo1"() !dbg !13 { + %1 = call i64 @"$ss6HasherV9_finalizeSiyF"(), !dbg !17 + ret i64 %1, !dbg !22 +} + +declare i64 @"$ss6HasherV9_finalizeSiyF"() local_unnamed_addr + +!llvm.dbg.cu = !{!0, !5} +!llvm.module.flags = !{!11, !12} + +!0 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !1, producer: "FooCU", isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug, imports: !2) +!1 = !DIFile(filename: "foo.swift", directory: "/") +!2 = !{!3} +!3 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !4, file: !1) +!4 = !DIModule(scope: null, name: "foo", includePath: "src") +!5 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !6, producer: "MainCU", isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug, globals: !7) +!6 = !DIFile(filename: "main.swift", directory: "/") +!7 = !{!8} +!8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression()) +!9 = distinct !DIGlobalVariable(name: "foos", linkageName: "$GlobalVarInMain", scope: !4, file: !6, line: 1, type: !10, isLocal: false, isDefinition: true) +!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", scope: !4, file: !1, runtimeLang: DW_LANG_Swift) +!11 = !{i32 7, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = distinct !DISubprogram(name: "hashValue.get", linkageName: "$hashValueGetInFoo1", scope: !10, file: !14, type: !15, spFlags: DISPFlagDefinition, unit: !0) +!14 = !DIFile(filename: "", directory: "") +!15 = !DISubroutineType(types: !16) +!16 = !{!10} +!17 = !DILocation(line: 0, scope: !18, inlinedAt: !19) +!18 = distinct !DISubprogram(name: "_hashValue", linkageName: "$HashValueInFoo", scope: null, file: !14, type: !15, spFlags: DISPFlagDefinition, unit: !0) +!19 = !DILocation(line: 0, scope: !20, inlinedAt: !22) +!20 = distinct !DILexicalBlock(scope: !21, file: !14) +!21 = distinct !DISubprogram(name: "hashValue.get", linkageName: "$hashValueGetInFoo2", scope: !10, file: !14, type: !15, spFlags: DISPFlagDefinition, unit: !0) +!22 = !DILocation(line: 0, scope: !13) diff --git a/llvm/test/DebugInfo/cross-cu-scope.ll b/llvm/test/DebugInfo/cross-cu-scope.ll --- a/llvm/test/DebugInfo/cross-cu-scope.ll +++ b/llvm/test/DebugInfo/cross-cu-scope.ll @@ -5,13 +5,11 @@ ; Reduced test case from PR35212. Two DISubprogram belong to a different CU but ; share a scope. Both are declarations and end up in the scope's CU. We want to ; check that the CU from the context DIE is used (rather than from the IR). -; This manifests itself by the DW_base_type ending up in the second CU, rather -; than in the first one as specified in the IR. +; This manifests itself by the DW_base_type ending up in the first CU, rather +; than in the second one as specified in the IR. (!16(usize) -> !15 -> !14 -> !13 -(unit:!0)-> CU(discriminator 0)) ; CHECK: DW_TAG_compile_unit ; CHECK-NEXT: discriminator 0 -; CHECK: DW_TAG_compile_unit -; CHECK-NEXT: discriminator 1 ; CHECK: DW_TAG_structure_type ; CHECK-NOT: NULL ; CHECK: DW_TAG_subprogram @@ -23,6 +21,10 @@ ; CHECK: DW_TAG_base_type ; CHECK-NOT: NULL ; CHECK: DW_AT_name{{.*}}"usize" +; CHECK: DW_TAG_compile_unit +; CHECK-NEXT: discriminator 1 +; CHECK: DW_TAG_structure_type +; CHECK: DW_TAG_subprogram define hidden void @foo() !dbg !4 { ret void, !dbg !7