[llvm] r203982 - Debug Info: Fix LTO type uniquing for C++ member declarations
David Blaikie
dblaikie at gmail.com
Fri Mar 14 18:09:29 PDT 2014
On Fri, Mar 14, 2014 at 4:08 PM, Adrian Prantl <aprantl at apple.com> wrote:
> Author: adrian
> Date: Fri Mar 14 18:08:25 2014
> New Revision: 203982
>
> URL: http://llvm.org/viewvc/llvm-project?rev=203982&view=rev
> Log:
> Debug Info: Fix LTO type uniquing for C++ member declarations
> based on the ODR.
Could we just use the same DIRef machinery for functions too?
> This adds an OdrMemberMap to DwarfDebug which is used to unique C++
> member function declarations based on the unique identifier of their
> containing class and their mangled name.
Why not just the mangled name? (see above - using the same DIRef machinery)
> We can't use the usual DIRef mechanism here because DIScopes are indexed
> using their entire MDNode, including decl_file and decl_line, which need
> not be unique (see testcase).
OK - not sure what you mean by this. I guess you mean DISubprogram is
a DIScope - but we could change the DISubprogram references without
changing the way that all DIScopes were referenced maybe? I'm not
sure.
Would be worth discussing this a bit, I hope...
>
> Prior to this change multiple redundant member function declarations would
> end up in the same uniqued DW_TAG_class_type.
>
> Added:
> llvm/trunk/test/Linker/type-unique-odr-a.ll
> llvm/trunk/test/Linker/type-unique-odr-b.ll
> Modified:
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=203982&r1=203981&r2=203982&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Fri Mar 14 18:08:25 2014
> @@ -364,6 +364,7 @@ bool DwarfDebug::isSubprogramContext(con
> // scope then create and insert DIEs for these variables.
> DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU,
> DISubprogram SP) {
> + SP = SPCU->getOdrUniqueSubprogram(resolve(SP.getContext()), SP);
> DIE *SPDie = SPCU->getDIE(SP);
>
> assert(SPDie && "Unable to find subprogram DIE!");
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=203982&r1=203981&r2=203982&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Fri Mar 14 18:08:25 2014
> @@ -353,6 +353,9 @@ class DwarfDebug : public AsmPrinterHand
> /// of in DwarfCompileUnit.
> DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap;
>
> + // Used to unique C++ member function declarations.
> + StringMap<const MDNode *> OdrMemberMap;
> +
> // Stores the current file ID for a given compile unit.
> DenseMap<unsigned, unsigned> FileIDCUMap;
> // Source id map, i.e. CUID, source filename and directory,
> @@ -702,6 +705,11 @@ public:
> return MDTypeNodeToDieMap.lookup(TypeMD);
> }
>
> + /// \brief Look up or create an entry in the OdrMemberMap.
> + const MDNode *&getOrCreateOdrMember(StringRef Key) {
> + return OdrMemberMap.GetOrCreateValue(Key).getValue();
> + }
> +
> /// \brief Emit all Dwarf sections that should come prior to the
> /// content.
> void beginModule();
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=203982&r1=203981&r2=203982&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Fri Mar 14 18:08:25 2014
> @@ -1405,12 +1405,33 @@ DIE *DwarfUnit::getOrCreateNameSpace(DIN
> return NDie;
> }
>
> +/// Unique C++ member function declarations based on their
> +/// context and mangled name.
> +DISubprogram
> +DwarfUnit::getOdrUniqueSubprogram(DIScope Context, DISubprogram SP) const {
> + if (!hasODR() ||
> + !Context.isCompositeType() ||
> + SP.getLinkageName().empty() ||
> + SP.isDefinition())
> + return SP;
> + // Create a key with the UID of the parent class and this SP's name.
> + Twine Key = SP.getContext().getName() + SP.getLinkageName();
> + const MDNode *&Entry = DD->getOrCreateOdrMember(Key.str());
> + if (!Entry)
> + Entry = &*SP;
> +
> + return DISubprogram(Entry);
> +}
> +
> /// getOrCreateSubprogramDIE - Create new DIE using SP.
> DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
> // Construct the context before querying for the existence of the DIE in case
> // such construction creates the DIE (as is the case for member function
> // declarations).
> - DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext()));
> + DIScope Context = resolve(SP.getContext());
> + DIE *ContextDIE = getOrCreateContextDIE(Context);
> + // Unique declarations based on the ODR, where applicable.
> + SP = getOdrUniqueSubprogram(Context, SP);
>
> DIE *SPDie = getDIE(SP);
> if (SPDie)
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h?rev=203982&r1=203981&r2=203982&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h Fri Mar 14 18:08:25 2014
> @@ -485,6 +485,28 @@ public:
>
> virtual DwarfCompileUnit &getCU() = 0;
>
> + /// \brief Return whether this compilation unit has the
> + /// one-definition-rule (ODR). In C++ this allows the compiler to
> + /// perform type unique during LTO.
> + bool hasODR() const {
> + switch (getLanguage()) {
> + case dwarf::DW_LANG_C_plus_plus:
> + case dwarf::DW_LANG_C_plus_plus_03:
> + case dwarf::DW_LANG_C_plus_plus_11:
> + // For all we care, the C++ part of the language has the ODR and
> + // ObjC methods are not represented in a way that they could be
> + // confused with C++ member functions.
> + case dwarf::DW_LANG_ObjC_plus_plus:
> + return true;
> + default:
> + return false;
> + }
> + }
> +
> + /// \brief Unique C++ member function declarations based on their
> + /// context+mangled name.
> + DISubprogram getOdrUniqueSubprogram(DIScope Context, DISubprogram SP) const;
> +
> protected:
> /// getOrCreateStaticMemberDIE - Create new static data member DIE.
> DIE *getOrCreateStaticMemberDIE(DIDerivedType DT);
>
> Added: llvm/trunk/test/Linker/type-unique-odr-a.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/type-unique-odr-a.ll?rev=203982&view=auto
> ==============================================================================
> --- llvm/trunk/test/Linker/type-unique-odr-a.ll (added)
> +++ llvm/trunk/test/Linker/type-unique-odr-a.ll Fri Mar 14 18:08:25 2014
> @@ -0,0 +1,94 @@
> +; REQUIRES: object-emission
> +;
> +; RUN: llvm-link %s %p/type-unique-odr-b.ll -S -o - | %llc_dwarf -filetype=obj -O0 | llvm-dwarfdump -debug-dump=info - | FileCheck %s
> +;
> +; Test ODR-based type uniquing for C++ class members.
> +; rdar://problem/15851313.
> +;
> +; $ cat -n type-unique-odr-a.cpp
> +; 1 class A {
> +; 2 int data;
> +; 3 protected:
> +; 4 void getFoo();
> +; 5 };
> +; 6
> +; 7 static void bar() {
> +; 8 A a;
> +; 9 }
> +; 10
> +; 11 void baz() { bar(); }
> +;; #include "ab.h"
> +; foo_t bar() {
> +; return A().getFoo();
> +; }
> +;
> +; CHECK: DW_TAG_subprogram
> +; CHECK-NEXT: DW_AT_MIPS_linkage_name {{.*}} "_Z3bazv"
> +; CHECK: DW_TAG_subprogram
> +; CHECK-NEXT: DW_AT_MIPS_linkage_name {{.*}} "_ZL3barv"
> +; CHECK: DW_TAG_class_type
> +; CHECK-NEXT: DW_AT_name {{.*}} "A"
> +; CHECK: DW_TAG_subprogram
> +; CHECK-NEXT: DW_AT_MIPS_linkage_name {{.*}} "_ZN1A6getFooEv"
> +; CHECK-NEXT: DW_AT_name {{.*}} "getFoo"
> +
> +; getFoo and A may only appear once.
> +; CHECK-NOT: {{(getFoo)|("A")}}
> +
> +
> +; ModuleID = 'type-unique-odr-a.cpp'
> +
> +%class.A = type { i32 }
> +
> +; Function Attrs: nounwind
> +define void @_Z3bazv() #0 {
> +entry:
> + call void @_ZL3barv(), !dbg !23
> + ret void, !dbg !23
> +}
> +
> +; Function Attrs: nounwind
> +define internal void @_ZL3barv() #0 {
> +entry:
> + %a = alloca %class.A, align 4
> + call void @llvm.dbg.declare(metadata !{%class.A* %a}, metadata !24), !dbg !25
> + ret void, !dbg !26
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata) #1
> +
> +attributes #0 = { nounwind }
> +attributes #1 = { nounwind readnone }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!20, !21}
> +!llvm.ident = !{!22}
> +
> +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5.0 ", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !14, metadata !2, metadata !2, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [<unknown>] [DW_LANG_C_plus_plus]
> +!1 = metadata !{metadata !"<unknown>", metadata !""}
> +!2 = metadata !{}
> +!3 = metadata !{metadata !4}
> +!4 = metadata !{i32 786434, metadata !5, null, metadata !"A", i32 1, i64 32, i64 32, i32 0, i32 0, null, metadata !6, i32 0, null, null, metadata !"_ZTS1A"} ; [ DW_TAG_class_type ] [A] [line 1, size 32, align 32, offset 0] [def] [from ]
> +!5 = metadata !{metadata !"type-unique-odr-a.cpp", metadata !""}
> +!6 = metadata !{metadata !7, metadata !9}
> +!7 = metadata !{i32 786445, metadata !5, metadata !"_ZTS1A", metadata !"data", i32 2, i64 32, i64 32, i64 0, i32 1, metadata !8} ; [ DW_TAG_member ] [data] [line 2, size 32, align 32, offset 0] [private] [from int]
> +!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
> +!9 = metadata !{i32 786478, metadata !5, metadata !"_ZTS1A", metadata !"getFoo", metadata !"getFoo", metadata !"_ZN1A6getFooEv", i32 4, metadata !10, i1 false, i1 false, i32 0, i32 0, null, i32 258, i1 false, null, null, i32 0, metadata !13, i32 4} ; [ DW_TAG_subprogram ] [line 4] [protected] [getFoo]
> +!10 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !11, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
> +!11 = metadata !{null, metadata !12}
> +!12 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 1088, metadata !"_ZTS1A"} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS1A]
> +!13 = metadata !{i32 786468}
> +!14 = metadata !{metadata !15, metadata !19}
> +!15 = metadata !{i32 786478, metadata !5, metadata !16, metadata !"baz", metadata !"baz", metadata !"_Z3bazv", i32 11, metadata !17, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @_Z3bazv, null, null, metadata !2, i32 11} ; [ DW_TAG_subprogram ] [line 11] [def] [baz]
> +!16 = metadata !{i32 786473, metadata !5} ; [ DW_TAG_file_type ] [type-unique-odr-a.cpp]
> +!17 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !18, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
> +!18 = metadata !{null}
> +!19 = metadata !{i32 786478, metadata !5, metadata !16, metadata !"bar", metadata !"bar", metadata !"_ZL3barv", i32 7, metadata !17, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @_ZL3barv, null, null, metadata !2, i32 7} ; [ DW_TAG_subprogram ] [line 7] [local] [def] [bar]
> +!20 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
> +!21 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
> +!22 = metadata !{metadata !"clang version 3.5.0 "}
> +!23 = metadata !{i32 11, i32 0, metadata !15, null}
> +!24 = metadata !{i32 786688, metadata !19, metadata !"a", metadata !16, i32 8, metadata !4, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [a] [line 8]
> +!25 = metadata !{i32 8, i32 0, metadata !19, null} ; [ DW_TAG_imported_declaration ]
> +!26 = metadata !{i32 9, i32 0, metadata !19, null}
>
> Added: llvm/trunk/test/Linker/type-unique-odr-b.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/type-unique-odr-b.ll?rev=203982&view=auto
> ==============================================================================
> --- llvm/trunk/test/Linker/type-unique-odr-b.ll (added)
> +++ llvm/trunk/test/Linker/type-unique-odr-b.ll Fri Mar 14 18:08:25 2014
> @@ -0,0 +1,86 @@
> +; RUN: true
> +; This file belongs to type-unique-odr-a.ll.
> +;
> +; Test ODR-based type uniquing for C++ class members.
> +; rdar://problem/15851313.
> +;
> +; $ cat -n type-unique-odr-b.cpp
> +; 1 // Make this declaration start on a different line.
> +; 2 class A {
> +; 3 int data;
> +; 4 protected:
> +; 5 void getFoo();
> +; 6 };
> +; 7
> +; 8 void A::getFoo() {}
> +; 9
> +; 10 static void bar() {}
> +; 11 void f() { bar(); };
> +
> +; ModuleID = 'type-unique-odr-b.cpp'
> +
> +%class.A = type { i32 }
> +
> +; Function Attrs: nounwind
> +define void @_ZN1A6getFooEv(%class.A* %this) #0 align 2 {
> +entry:
> + %this.addr = alloca %class.A*, align 8
> + store %class.A* %this, %class.A** %this.addr, align 8
> + call void @llvm.dbg.declare(metadata !{%class.A** %this.addr}, metadata !24), !dbg !26
> + %this1 = load %class.A** %this.addr
> + ret void, !dbg !27
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata) #1
> +
> +; Function Attrs: nounwind
> +define void @_Z1fv() #0 {
> +entry:
> + call void @_ZL3barv(), !dbg !28
> + ret void, !dbg !28
> +}
> +
> +; Function Attrs: nounwind
> +define internal void @_ZL3barv() #0 {
> +entry:
> + ret void, !dbg !29
> +}
> +
> +attributes #0 = { nounwind }
> +attributes #1 = { nounwind readnone }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!21, !22}
> +!llvm.ident = !{!23}
> +
> +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5.0 ", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !14, metadata !2, metadata !2, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [<unknown>] [DW_LANG_C_plus_plus]
> +!1 = metadata !{metadata !"<unknown>", metadata !""}
> +!2 = metadata !{}
> +!3 = metadata !{metadata !4}
> +!4 = metadata !{i32 786434, metadata !5, null, metadata !"A", i32 2, i64 32, i64 32, i32 0, i32 0, null, metadata !6, i32 0, null, null, metadata !"_ZTS1A"} ; [ DW_TAG_class_type ] [A] [line 2, size 32, align 32, offset 0] [def] [from ]
> +!5 = metadata !{metadata !"type-unique-odr-b.cpp", metadata !""}
> +!6 = metadata !{metadata !7, metadata !9}
> +!7 = metadata !{i32 786445, metadata !5, metadata !"_ZTS1A", metadata !"data", i32 3, i64 32, i64 32, i64 0, i32 1, metadata !8} ; [ DW_TAG_member ] [data] [line 3, size 32, align 32, offset 0] [private] [from int]
> +!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
> +!9 = metadata !{i32 786478, metadata !5, metadata !"_ZTS1A", metadata !"getFoo", metadata !"getFoo", metadata !"_ZN1A6getFooEv", i32 5, metadata !10, i1 false, i1 false, i32 0, i32 0, null, i32 258, i1 false, null, null, i32 0, metadata !13, i32 5} ; [ DW_TAG_subprogram ] [line 5] [protected] [getFoo]
> +!10 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !11, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
> +!11 = metadata !{null, metadata !12}
> +!12 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 1088, metadata !"_ZTS1A"} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS1A]
> +!13 = metadata !{i32 786468}
> +!14 = metadata !{metadata !15, metadata !16, metadata !20}
> +!15 = metadata !{i32 786478, metadata !5, metadata !"_ZTS1A", metadata !"getFoo", metadata !"getFoo", metadata !"_ZN1A6getFooEv", i32 8, metadata !10, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (%class.A*)* @_ZN1A6getFooEv, null, metadata !9, metadata !2, i32 8} ; [ DW_TAG_subprogram ] [line 8] [def] [getFoo]
> +!16 = metadata !{i32 786478, metadata !5, metadata !17, metadata !"f", metadata !"f", metadata !"_Z1fv", i32 11, metadata !18, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @_Z1fv, null, null, metadata !2, i32 11} ; [ DW_TAG_subprogram ] [line 11] [def] [f]
> +!17 = metadata !{i32 786473, metadata !5} ; [ DW_TAG_file_type ] [type-unique-odr-b.cpp]
> +!18 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !19, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
> +!19 = metadata !{null}
> +!20 = metadata !{i32 786478, metadata !5, metadata !17, metadata !"bar", metadata !"bar", metadata !"_ZL3barv", i32 10, metadata !18, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @_ZL3barv, null, null, metadata !2, i32 10} ; [ DW_TAG_subprogram ] [line 10] [local] [def] [bar]
> +!21 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
> +!22 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
> +!23 = metadata !{metadata !"clang version 3.5.0 "}
> +!24 = metadata !{i32 786689, metadata !15, metadata !"this", null, i32 16777216, metadata !25, i32 1088, i32 0} ; [ DW_TAG_arg_variable ] [this] [line 0]
> +!25 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !"_ZTS1A"} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from _ZTS1A]
> +!26 = metadata !{i32 0, i32 0, metadata !15, null}
> +!27 = metadata !{i32 8, i32 0, metadata !15, null} ; [ DW_TAG_imported_declaration ]
> +!28 = metadata !{i32 11, i32 0, metadata !16, null}
> +!29 = metadata !{i32 10, i32 0, metadata !20, null}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list