This is an archive of the discontinued LLVM Phabricator instance.

Do not split variables definitions into 2 DIEs.
Needs ReviewPublic

Authored by friss on Sep 23 2014, 1:05 AM.

Details

Summary

This is currently done for variables that aren't a file or function scope, but
the reason is unclear and might be historical. Static class member where
handled specifically and always generated a DW_TAG_member declarartion and
a DW_TAG_variable instance. This patch removes all these and only ever emits
one definition DIE, be it a DW_TAG_variable or a DW_TAG_member.

It would be good to get a gdb testsuite run with the patch applied before it
goes in to prevent any fallback (and I guess this kind of patch has a huge
fallback potential). I'll try to run lldb tests on my side.

Diff Detail

Event Timeline

friss updated this revision to Diff 13974.Sep 23 2014, 1:05 AM
friss retitled this revision from to Do not split variables definitions into 2 DIEs..
friss added reviewers: dblaikie, echristo, aprantl.
friss updated this object.
friss added a subscriber: Unknown Object (MLST).
dblaikie added inline comments.Sep 23 2014, 8:31 AM
test/DebugInfo/X86/gnu-public-names.ll
56

This actually seems like it /might/ be a reasonable place for a separate declaration and definition, since the user wrote an out of line definition.

What location do we attribute the definition to? It might be worth checking the decl_line attribute in this test. Did we previously attribute the declaration and definition to their respective lines, or just duplicate one/the other of them?

How does this compare to other nested definitions (I suppose for functions in namespaces we don't emit both distinguishing the declaration and definition in cases like: "namespace x { void func(); } void x::func() {}" so there's arguably no reason to similarly for variables)

friss added inline comments.Sep 23 2014, 10:06 AM
test/DebugInfo/X86/gnu-public-names.ll
56

I would agree totally if we somehow emitted information corresponding to the definition location in the debug info. But the only line information that we provide is the one of the declaration in all cases (the attribute is called decl_line, so maybe that's really how it should be). If the definition DIE has no overlapping attributes with the declaration, I don't see a reason to keep both.
There is one thing that is special to class members though. If we only emit a definition (what the patch actually does), it will be inside the type. And this is be an issue if we want to emit type units, isn't it? Maybe this whole split-if-not-file/function-scope heuristic is to only ever emit declarations into classes.
For functions in namespaces, we only emit one definition DIE, but for class methods we split declaration and definition. So maybe we should really keep the class type exempt of definitions.

friss updated this revision to Diff 14686.Oct 9 2014, 4:19 PM

I finally managed to get some test results for this patch. Indeed putting the static member variable definition broke some lldb tests, thus I left the behavior unchanged for static member variables. This is still a nice cleanup of the global variable DIE creation logic.

David, if you still like the direction I'd appreciate if you could give it a test run on the GDB testsuite to see if it doesn't break anything there. Note that I haven't included an additional test for type units as I removed the behavior change that might have caused issues with that usecase.

dblaikie edited edge metadata.Oct 20 2014, 2:06 PM

I've checked this out on the GDB test suite & it seems fine.

Looking at the code itself, I think it could be made a bit more
obvious/uniform to have VariableDIE always refer to the definition and have
just a single conditional to decide whether to attach the
DW_AT_specification or not.

Actually this works pretty well & even adds another source fidelity
benefit, allowing the definition, while out-of-line of the class, to be
attributed to the scope in which the definition occurs (eg: namespace x {
struct foo { static int i; }; int foo::i; } - putting the definition in
namespace 'x' instead of just forcing it out to the global namespace) and
exposes a bug in Clang where the definition is scoped to the decl context
instead of the lexical context. (patch attached to show a slightly
short-sighted fix there)

If we did a few more smart things in the frontend, we could get better
fidelity for declarations/definitions of namespace/global variables -
removing the weird special case introduced with my patch. Probably the
right thing here is to optimize in the frontend, if the definition appears
in the decl context (eg: if the global variable's decl context is the same
as the lexical context) then just produce the definition. If the decl and
lexical context differ, produce both a declaration (in the decl context)
and a definition (in the lexical context) - this would be the best source
fidelity, but probably isn't too worthwhile.

Oh, and if we wanted to be really good here, we could make sure we emit any
attributes onto the definition that differ from the declaration - note GCC
does the right thing here, putting DW_AT_decl_line/file on the definitions
if the line/file happens to be different from the declaration's line/file.
We don't do that - we just put nothing on the definition (& I don't think
we do this for function declarations/definitions either (again, here, GCC
gets this right)... could, but probably not important)