[lldb-dev] [llvm-dev] Adding DWARF5 accelerator table support to llvm

via lldb-dev lldb-dev at lists.llvm.org
Fri Jun 15 09:23:28 PDT 2018


> From: Greg Clayton [mailto:clayborg at gmail.com] 
>
> ...
> If a class has templated functions, they will only be in the DWARF is a
> specialization was created and used. If you have a class that looks like:
>
> class A {
>   A();
>   <template T> void Foo(T t);
> };
>
> And then you have main.cpp that has a "double" and "int" specialization,
> the class definition in DWARF looks like:
>
> class A {
>   A();
>   <int> void Foo(int t);
>   <double> void Foo(double t);
> };
>
> In another source file, say foo.cpp, if its use of class A doesn't
> specialize Foo, we have a class definition in DWARF that looks like:
>
> class A {
>   A();
> };
>

I think it would be more instructive to think about a case where 
main.cpp had Foo<int> and foo.cpp had Foo<double>.

> With the C++ ODR rules, we can pick any of the "class A" definitions
> whose qualified name matches ("::A") and has the same decl file + 
> decl line. So when parsing "class A", the DWARF parser will use the
> accelerator tables to find all instances of "class A", and it will
> pick on and use it and this will become the one true definition for
> "class A".

FTR, the Sony debugger finds them all and then merges them into the one
true definition, because there's no promise that any one description is
a superset of the rest.

> This is because DWARF is only emitted for template functions when
> there is a specialization, that mean any definition of "class A" might
> or might not include any definition for "<template T> A::Foo(T t);".

It's not just template functions, you know; the implicit ctors/dtors
might or might not be in any given description.  Those are also only
instantiated and described in CUs that require them.

> When we copy types between ASTs, everything is fine if the classes
> match (no copy needs to be made), but things go wrong if things
> don't match and this causes expression errors. 
>
> Some ways to fix this:
> 1 - anytime we need _any_ C++ class, we must dig up all definitions
> and check _all_ DW_TAG_subprogram DIEs within the class to check if
> any functions have templates and use the class with the most
> specializations

This still fails in my "more instructive" case.  The accelerator table
does make it fast to find all the classes with the same name, and you
can then merge them.

> 2 - have DWARF actually emit the template function info all the time
> as a type T, not a specialization, so we always have the full definition

Hm.  You mean a subroutine_type with template_parameter children that
don't have actual values?  That would give you a pattern, but not tell
you what/where definitions exist.  I don't see how that can help?

> 3 - have some accelerator table that explicitly points us to all
> specializations of class methods given a class name

So you want an accelerator to tell you what bits you need to pick up
from the various descriptions in order to construct the overall
superset definition, which would be a little cheaper than parsing
each entire class description (which you can already find through
the existing accelerator tables).  I can see that.

> Solution #1 would cause us to dig through all definitions of all C++
> classes all the time when parsing DWARF to check if definitions of
> the classes had template methods. And we would need to find the class
> that has the most template methods. This would cause us to parse much
> more of the debug info all of the time and cause increased memory
> consumption and performance regressions.

It would be cheap to put a flag on the class DIE that tells you there
are template methods to go look for.  Then you incur the cost only
when necessary.  And the accelerator table makes it fast to find the
other class descriptions.

> Solution #2: not sure if DWARF even supports generic template
> definitions where the template isn't specialized. And, how would we
> be able to tell DWARF that emits only specialized templates vs one
> that has generic definitions...

Right, DWARF today doesn't do that, although as I mentioned earlier
conjuring up a subroutine_type with template parameters would not
appear to be any more helpful than a simple flag on the class.

>
> Solution #3 will require compiler changes.

Well, so does #2.

> So this is another vote to support the ability for a given class
> to be able to locate all of its functions, kind of like we need
> for Objective C where the class definition doesn't contain all of
> methods, so we have the .apple_objc section that provides this
> mapping for us. We would need something similar for C++.
>
> So maybe a possible solution is some sort of section that can
> specify all of the DIEs related to a class that are not contained
> in the class hierarchy itself. This would work for Objective C
> and for C++.
>
> Thoughts?
>
> Greg

So, would it be helpful to have a flag on the class that tells you
whether there are method instantiations to go look for?  My
impression is that templated class methods are unusual so it would
save the performance cost a lot of the time right there.

I don't know enough about Obj-C to say whether it can know up front
there are potentially other methods elsewhere.

--paulr


More information about the lldb-dev mailing list