[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