[llvm] r181271 - DebugInfo: Support imported modules in lexical blocks

David Blaikie dblaikie at gmail.com
Mon May 6 16:42:04 PDT 2013


Just to explain some parts of this change (open to
commentary/criticism, of course)...

On Mon, May 6, 2013 at 4:33 PM, David Blaikie <dblaikie at gmail.com> wrote:
> Author: dblaikie
> Date: Mon May  6 18:33:07 2013
> New Revision: 181271
>
> URL: http://llvm.org/viewvc/llvm-project?rev=181271&view=rev
> Log:
> DebugInfo: Support imported modules in lexical blocks
>
> Modified:
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
>     llvm/trunk/test/DebugInfo/namespace.ll
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h?rev=181271&r1=181270&r2=181271&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Mon May  6 18:33:07 2013
> @@ -94,9 +94,6 @@ class CompileUnit {
>    /// DWARF version doesn't handle the language, return -1.
>    int64_t getDefaultLowerBound() const;
>
> -  /// getOrCreateContextDIE - Get context owner's DIE.
> -  DIE *getOrCreateContextDIE(DIDescriptor Context);
> -
>  public:
>    CompileUnit(unsigned UID, unsigned L, DIE *D, AsmPrinter *A, DwarfDebug *DW,
>                DwarfUnits *);
> @@ -372,6 +369,9 @@ public:
>    /// createStaticMemberDIE - Create new static data member DIE.
>    DIE *createStaticMemberDIE(DIDerivedType DT);
>
> +  /// getOrCreateContextDIE - Get context owner's DIE.
> +  DIE *getOrCreateContextDIE(DIDescriptor Context);
> +
>  private:
>
>    // DIEValueAllocator - All DIEValues are allocated through this allocator.
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=181271&r1=181270&r2=181271&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Mon May  6 18:33:07 2013
> @@ -94,6 +94,12 @@ static cl::opt<DefaultOnOff> SplitDwarf(
>  namespace {
>    const char *DWARFGroupName = "DWARF Emission";
>    const char *DbgTimerName = "DWARF Debug Writer";
> +
> +  struct CompareFirst {
> +    template <typename T> bool operator()(const T &lhs, const T &rhs) const {
> +      return lhs.first < rhs.first;
> +    }
> +  };
>  } // end anonymous namespace
>
>  //===----------------------------------------------------------------------===//
> @@ -597,9 +603,15 @@ DIE *DwarfDebug::constructScopeDIE(Compi
>    }
>    else {
>      // There is no need to emit empty lexical block DIE.
> -    if (Children.empty())

Previously we only emitted lexical blocks into the DWARF when the
block had one or more variables in it. Now we want to make sure we
emit lexical blocks even if there are no variables but at least one
DW_TAG_imported_module (excuse the "entity" naming - that's forward
looking to a future rename so we can support
DW_TAG_imported_declarations with similar machinery).

> +    std::pair<ImportedEntityMap::const_iterator,
> +              ImportedEntityMap::const_iterator> Range = std::equal_range(
> +        ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(),
> +        std::pair<const MDNode *, const MDNode *>(DS, 0), CompareFirst());
> +    if (Children.empty() && Range.first == Range.second)
>        return NULL;
>      ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
> +    for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second; ++i)
> +      constructImportedModuleDIE(TheCU, i->second, ScopeDIE);

Then we need to emit the imported modules immediately, since we don't
have any way of looking up the lexical scope DIEs later on.

>    }
>
>    if (!ScopeDIE) return NULL;
> @@ -768,6 +780,24 @@ void DwarfDebug::constructImportedModule
>    DIImportedModule Module(N);
>    if (!Module.Verify())
>      return;
> +  if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext()))

And just don't emit any where we can't find/create the context DIE -
those are the lexical block ones. (could an some asserts to verify
this)

> +    constructImportedModuleDIE(TheCU, Module, D);
> +}
> +
> +void DwarfDebug::constructImportedModuleDIE(CompileUnit *TheCU, const MDNode *N,
> +                                            DIE *Context) {
> +  DIImportedModule Module(N);
> +  if (!Module.Verify())
> +    return;
> +  return constructImportedModuleDIE(TheCU, Module, Context);
> +}
> +
> +void DwarfDebug::constructImportedModuleDIE(CompileUnit *TheCU,
> +                                            const DIImportedModule &Module,
> +                                            DIE *Context) {
> +  assert(Module.Verify() &&
> +         "Use one of the MDNode * overloads to handle invalid metadata");
> +  assert(Context && "Should always have a context for an imported_module");
>    DIE *IMDie = new DIE(dwarf::DW_TAG_imported_module);
>    TheCU->insertDIE(Module, IMDie);
>    DIE *NSDie = TheCU->getOrCreateNameSpace(Module.getNameSpace());
> @@ -777,7 +807,7 @@ void DwarfDebug::constructImportedModule
>    TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, 0, FileID);
>    TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, 0, Module.getLineNumber());
>    TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, dwarf::DW_FORM_ref4, NSDie);
> -  TheCU->addToContextOwner(IMDie, Module.getContext());
> +  Context->addChild(IMDie);
>  }
>
>  // Emit all Dwarf sections that should come prior to the content. Create
> @@ -801,6 +831,13 @@ void DwarfDebug::beginModule() {
>    for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
>      DICompileUnit CUNode(CU_Nodes->getOperand(i));
>      CompileUnit *CU = constructCompileUnit(CUNode);
> +    DIArray ImportedModules = CUNode.getImportedModules();
> +    for (unsigned i = 0, e = ImportedModules.getNumElements(); i != e; ++i)
> +      ScopesWithImportedEntities.push_back(std::make_pair(
> +          DIImportedModule(ImportedModules.getElement(i)).getContext(),
> +          ImportedModules.getElement(i)));
> +    std::sort(ScopesWithImportedEntities.begin(),
> +              ScopesWithImportedEntities.end(), CompareFirst());
>      DIArray GVs = CUNode.getGlobalVariables();
>      for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
>        CU->createGlobalVariableDIE(GVs.getElement(i));
> @@ -815,7 +852,6 @@ void DwarfDebug::beginModule() {
>        CU->getOrCreateTypeDIE(RetainedTypes.getElement(i));
>      // Emit imported_modules last so that the relevant context is already
>      // available.
> -    DIArray ImportedModules = CUNode.getImportedModules();
>      for (unsigned i = 0, e = ImportedModules.getNumElements(); i != e; ++i)
>        constructImportedModuleDIE(CU, ImportedModules.getElement(i));
>      // If we're splitting the dwarf out now that we've got the entire
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=181271&r1=181270&r2=181271&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Mon May  6 18:33:07 2013
> @@ -433,6 +433,10 @@ class DwarfDebug {
>    // Holder for the skeleton information.
>    DwarfUnits SkeletonHolder;
>
> +  typedef SmallVector<std::pair<const MDNode *, const MDNode *>, 32>
> +    ImportedEntityMap;

Using a sorted vector as per the LLVM programming guide. We build it
once, sort it once, then access it frequently. SmallVector base size
of 32 is a wild stab in the dark.

> +  ImportedEntityMap ScopesWithImportedEntities;
> +
>  private:
>
>    void addScopeVariable(LexicalScope *LS, DbgVariable *Var);
> @@ -558,6 +562,15 @@ private:
>    /// \brief Construct import_module DIE.
>    void constructImportedModuleDIE(CompileUnit *TheCU, const MDNode *N);
>
> +  /// \brief Construct import_module DIE.
> +  void constructImportedModuleDIE(CompileUnit *TheCU, const MDNode *N,
> +                                  DIE *Context);
> +
> +  /// \brief Construct import_module DIE.
> +  void constructImportedModuleDIE(CompileUnit *TheCU,
> +                                  const DIImportedModule &Module,
> +                                  DIE *Context);
> +
>    /// \brief Register a source line with debug info. Returns the unique
>    /// label that was emitted and which provides correspondence to the
>    /// source line list.
>
> Modified: llvm/trunk/test/DebugInfo/namespace.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/namespace.ll?rev=181271&r1=181270&r2=181271&view=diff
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/namespace.ll (original)
> +++ llvm/trunk/test/DebugInfo/namespace.ll Mon May  6 18:33:07 2013
> @@ -3,7 +3,7 @@
>  ; RUN: llc -O0 -filetype=obj < %s > %t
>  ; RUN: llvm-dwarfdump %t | FileCheck %s
>  ; CHECK: debug_info contents
> -; CHECK: DW_TAG_namespace
> +; CHECK: [[NS1:0x[0-9a-f]*]]:{{ *}}DW_TAG_namespace
>  ; CHECK-NEXT: DW_AT_name{{.*}} = "A"
>  ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F1:[0-9]]])
>  ; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x03)
> @@ -15,14 +15,31 @@
>  ; CHECK-NOT: NULL
>  ; CHECK: DW_TAG_variable
>  ; CHECK-NEXT: DW_AT_name{{.*}}= "i"
> +; CHECK: NULL
> +; CHECK-NOT: NULL
> +; CHECK: DW_TAG_imported_module
> +; This is a bug, it should be in F2 but it inherits the file from its
> +; enclosing scope
> +; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F1]])
> +; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x04)
> +; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS2]]})
> +
>  ; CHECK: DW_TAG_subprogram
>  ; CHECK-NEXT: DW_AT_MIPS_linkage_name
>  ; CHECK-NEXT: DW_AT_name{{.*}}= "func"
>  ; CHECK-NOT: NULL
>  ; CHECK: DW_TAG_imported_module
>  ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]])
> -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x07)
> +; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x0e)
> +; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS1]]})
> +; CHECK-NOT: NULL
> +; CHECK: DW_TAG_lexical_block
> +; CHECK-NOT: NULL
> +; CHECK: DW_TAG_imported_module
> +; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]])
> +; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x0b)
>  ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS2]]})
> +
>  ; CHECK: file_names[  [[F1]]]{{.*}}debug-info-namespace.cpp
>  ; CHECK: file_names[  [[F2]]]{{.*}}foo.cpp
>
> @@ -33,40 +50,81 @@
>  ; namespace B {
>  ; int i;
>  ; }
> +; using namespace B;
>  ; }
>  ;
> -; int func() {
> -;   using namespace A::B;
> -;   return i;
> +; using namespace A;
> +;
> +; int func(bool b) {
> +;   if (b) {
> +;     using namespace A::B;
> +;     return i;
> +;   }
> +;   using namespace A;
> +;   return B::i;
>  ; }
>
>  @_ZN1A1B1iE = global i32 0, align 4
>
> -; Function Attrs: nounwind uwtable
> -define i32 @_Z4funcv() #0 {
> +; Function Attrs: nounwind uwtable
> +define i32 @_Z4funcb(i1 zeroext %b) #0 {
>  entry:
> -  %0 = load i32* @_ZN1A1B1iE, align 4, !dbg !16
> -  ret i32 %0, !dbg !16
> +  %retval = alloca i32, align 4
> +  %b.addr = alloca i8, align 1
> +  %frombool = zext i1 %b to i8
> +  store i8 %frombool, i8* %b.addr, align 1
> +  call void @llvm.dbg.declare(metadata !{i8* %b.addr}, metadata !21), !dbg !22
> +  %0 = load i8* %b.addr, align 1, !dbg !23
> +  %tobool = trunc i8 %0 to i1, !dbg !23
> +  br i1 %tobool, label %if.then, label %if.end, !dbg !23
> +
> +if.then:                                          ; preds = %entry
> +  %1 = load i32* @_ZN1A1B1iE, align 4, !dbg !24
> +  store i32 %1, i32* %retval, !dbg !24
> +  br label %return, !dbg !24
> +
> +if.end:                                           ; preds = %entry
> +  %2 = load i32* @_ZN1A1B1iE, align 4, !dbg !25
> +  store i32 %2, i32* %retval, !dbg !25
> +  br label %return, !dbg !25
> +
> +return:                                           ; preds = %if.end, %if.then
> +  %3 = load i32* %retval, !dbg !26
> +  ret i32 %3, !dbg !26
>  }
>
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata) #1
> +
>  attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone }
>
>  !llvm.dbg.cu = !{!0}
>
> -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.3 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !10, metadata !14, metadata !""} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/llvm/src/tools/clang//usr/local/google/home/blaikie/dev/llvm/src/tools/clang/test/CodeGenCXX/debug-info-namespace.cpp] [DW_LANG_C_plus_plus]
> +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.3 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !11, metadata !15, metadata !""} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/llvm/src/tools/clang//usr/local/google/home/blaikie/dev/llvm/src/tools/clang/test/CodeGenCXX/debug-info-namespace.cpp] [DW_LANG_C_plus_plus]
>  !1 = metadata !{metadata !"/usr/local/google/home/blaikie/dev/llvm/src/tools/clang/test/CodeGenCXX/debug-info-namespace.cpp", metadata !"/usr/local/google/home/blaikie/dev/llvm/src/tools/clang"}
>  !2 = metadata !{i32 0}
>  !3 = metadata !{metadata !4}
> -!4 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"func", metadata !"func", metadata !"_Z4funcv", i32 6, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @_Z4funcv, null, null, metadata !2, i32 6} ; [ DW_TAG_subprogram ] [line 6] [def] [func]
> +!4 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"func", metadata !"func", metadata !"_Z4funcb", i32 9, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i1)* @_Z4funcb, null, null, metadata !2, i32 9} ; [ DW_TAG_subprogram ] [line 9] [def] [func]
>  !5 = metadata !{metadata !"foo.cpp", metadata !"/usr/local/google/home/blaikie/dev/llvm/src/tools/clang"}
> -!6 = metadata !{i32 786473, metadata !5}          ; [ DW_TAG_file_type ] [/usr/local/google/home/blaikie/dev/llvm/src/tools/clang/foo.cpp]
> +!6 = metadata !{i32 786473, metadata !5}          ; [ DW_TAG_file_type ] [/usr/local/google/home/blaikie/dev/llvm/build/clang/debug/foo.cpp]
>  !7 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
> -!8 = metadata !{metadata !9}
> +!8 = metadata !{metadata !9, metadata !10}
>  !9 = 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]
> -!10 = metadata !{metadata !11}
> -!11 = metadata !{i32 786484, i32 0, metadata !12, metadata !"i", metadata !"i", metadata !"_ZN1A1B1iE", metadata !6, i32 2, metadata !9, i32 0, i32 1, i32* @_ZN1A1B1iE, null} ; [ DW_TAG_variable ] [i] [line 2] [def]
> -!12 = metadata !{i32 786489, metadata !5, metadata !13, metadata !"B", i32 1} ; [ DW_TAG_namespace ] [B] [line 1]
> -!13 = metadata !{i32 786489, metadata !1, null, metadata !"A", i32 3} ; [ DW_TAG_namespace ] [A] [line 3]
> -!14 = metadata !{metadata !15}
> -!15 = metadata !{i32 786490, metadata !4, metadata !12, i32 7} ; [ DW_TAG_imported_module ]
> -!16 = metadata !{i32 8, i32 0, metadata !4, null}
> +!10 = metadata !{i32 786468, null, null, metadata !"bool", i32 0, i64 8, i64 8, i64 0, i32 0, i32 2} ; [ DW_TAG_base_type ] [bool] [line 0, size 8, align 8, offset 0, enc DW_ATE_boolean]
> +!11 = metadata !{metadata !12}
> +!12 = metadata !{i32 786484, i32 0, metadata !13, metadata !"i", metadata !"i", metadata !"_ZN1A1B1iE", metadata !6, i32 2, metadata !9, i32 0, i32 1, i32* @_ZN1A1B1iE, null} ; [ DW_TAG_variable ] [i] [line 2] [def]
> +!13 = metadata !{i32 786489, metadata !5, metadata !14, metadata !"B", i32 1} ; [ DW_TAG_namespace ] [B] [line 1]
> +!14 = metadata !{i32 786489, metadata !1, null, metadata !"A", i32 3} ; [ DW_TAG_namespace ] [A] [line 3]
> +!15 = metadata !{metadata !16, metadata !17, metadata !18, metadata !20}
> +!16 = metadata !{i32 786490, metadata !14, metadata !13, i32 4} ; [ DW_TAG_imported_module ]
> +!17 = metadata !{i32 786490, metadata !0, metadata !14, i32 7} ; [ DW_TAG_imported_module ]
> +!18 = metadata !{i32 786490, metadata !19, metadata !13, i32 11} ; [ DW_TAG_imported_module ]
> +!19 = metadata !{i32 786443, metadata !5, metadata !4, i32 10, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/usr/local/google/home/blaikie/dev/llvm/build/clang/debug/foo.cpp]
> +!20 = metadata !{i32 786490, metadata !4, metadata !14, i32 14} ; [ DW_TAG_imported_module ]
> +!21 = metadata !{i32 786689, metadata !4, metadata !"b", metadata !6, i32 16777225, metadata !10, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [b] [line 9]
> +!22 = metadata !{i32 9, i32 0, metadata !4, null}
> +!23 = metadata !{i32 10, i32 0, metadata !4, null}
> +!24 = metadata !{i32 12, i32 0, metadata !19, null}
> +!25 = metadata !{i32 15, i32 0, metadata !4, null}
> +!26 = metadata !{i32 16, i32 0, metadata !4, 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