[PATCH] D96035: [dsymutil][DWARFlinker] implement separate multi-thread processing for compile units.

Alexey Lapshin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 5 05:24:37 PST 2022


avl added a comment.

In D96035#3221040 <https://reviews.llvm.org/D96035#3221040>, @clayborg wrote:

> So I am currently just looking at the content of the DWARF that is produced when using "--use-dlnext". Right now the main issue is it seems that types declared in an anonymous namespace in implementation files are all being moved to the "__type_table" die:
>
>   0x0000000b: DW_TAG_compile_unit
>                 DW_AT_producer	("DWARFLinker lib")
>                 DW_AT_language	(DW_LANG_C_plus_plus_14)
>                 DW_AT_name	("__type_table")
>                 DW_AT_stmt_list	(0x00000000)
>                 DW_AT_comp_dir	("")
>
> One quick example is LVBase from APValue.cpp line 165:
>
>   namespace {
>     struct LVBase {
>       APValue::LValueBase Base;
>       CharUnits Offset;
>       unsigned PathLength;
>       bool IsNullPtr : 1;
>       bool IsOnePastTheEnd : 1;
>     };
>   }
>
> Which produces a type in the "__type_table" compile unit:
>
>   0x000000a6:   DW_TAG_namespace
>                   DW_AT_decl_file	("/Users/gclayton/Documents/src/lldb/clean/Debug/lib/libclangAST.a(APValue.cpp.o)")
>   
>   0x000000a9:     DW_TAG_structure_type
>                     DW_AT_calling_convention	(DW_CC_pass_by_value)
>                     DW_AT_name	("LVBase")
>                     DW_AT_byte_size	(0x20)
>                     DW_AT_decl_file	("/Users/gclayton/Documents/src/lldb/clean/llvm-project/clang/lib/AST/APValue.cpp")
>                     DW_AT_decl_line	(166)
>   
>   0x000000b3:       DW_TAG_subprogram
>                       DW_AT_name	("LVBase")
>                       DW_AT_declaration	(true)
>                       DW_AT_artificial	(true)
>                       DW_AT_external	(true)
>
> I would think we should leave these types in the original compile unit as that will be the only compile unit that will use these types. Right now you are moving them to the "__type_table" compile unit so they can be uniqued, but they don't need to be uniqued. This is pretty C++ specific though.

The reason why the content of anonymous namespace(as well as types defined inside subprograms) is moved into the type table - is handling parameterized types.
If we have a type defined inside an anonymous namespace and this type is not moved into the type table and this type is used as a parameter of another class then we could not move that another class into the type table also. That another class might be used in other places and have other dependencies. Finally, the type from the anonymous namespace might prevent moving a lot of classes into the type table. Please check the following example:

----------------------------

cat main.cpp

  char foo1 (void);
  long foo2 (void);
  
  int main ( void ) {
    return foo1() + foo2();
  }

----------------------------

cat a.h

  struct A {
    template <class T>
    T foo () {
      return T();
    }
  };

----------------------------

cat foo1.cpp

  #include "a.h"
  
  char foo1 (void) {
    return A().foo<char>(); 
  }

----------------------------

cat foo2.cpp

  #include "a.h"
  
  namespace {
  
  struct B {
    long m1;
  };
  
  B internal (void) {
    return A().foo<B>();
  }
  
  }
  
  long foo2 (void ) {
    return internal().m1;
  }

In dwarf we have a following die :

  DW_TAG_structure_type
    DW_AT_calling_convention        (DW_CC_pass_by_value)
    DW_AT_name      ("A")
    DW_AT_byte_size (0x01)
    DW_AT_decl_file ("/home/avl/test_templates1/./a.h")
    DW_AT_decl_line (1)
  
    DW_TAG_subprogram
      DW_AT_linkage_name    ("_ZN1A3fooIN12_GLOBAL__N_11BEEET_v")
      DW_AT_name    ("foo<(anonymous namespace)::B>")
      DW_AT_decl_file       ("/home/avl/test_templates1/./a.h")
      DW_AT_decl_line       (3)
      DW_AT_type    (0x0000016d "(anonymous namespace)::B")
      DW_AT_declaration     (true)
  
      DW_TAG_template_type_parameter
        DW_AT_type  (0x0000016d "(anonymous namespace)::B")
        DW_AT_name  ("T")
  
      DW_TAG_formal_parameter
        DW_AT_type  (0x000001b3 "A *")
        DW_AT_artificial    (true)
  
      NULL
    NULL

The method "foo<(anonymous namespace)::B>" prevents moving "A"(from foo2.cpp) into the type table.
The "A" structure might contain a lot of data and many other types might depend on "A".
Finally a big piece of DWARF(from NON-anonymous namespaces) would be left in place 
and is not de duplicated.

To resolve this problem this patch moves all types into the type table. So that "anonymous"
types would not prevent other types from de duplication.

There probably might be implemented smarter solution, which will be able to "split" type "A" so that all not depending part of it would be moved into the type table but
part related to the types defined in anonymous namespace would left in place. That is more complex solution and is not implemented yet. This patch implements types merging. Types splitting might be done if current solution is not good enough.

> The namespace also has the object file path as the decl file. If we are going to move the type, wouldn't it be better to use the compile unit's path like:
>
>   0x000000a6:   DW_TAG_namespace
>                   DW_AT_decl_file	("/Users/gclayton/Documents/src/lldb/clean/llvm-project/clang/lib/AST/APValue.cpp")

yes, it supposed to be compile unit path. will check it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96035/new/

https://reviews.llvm.org/D96035



More information about the llvm-commits mailing list