[PATCH] Avoid empty .debug_loc entries and lists
Duncan P. N. Exon Smith
dexonsmith at apple.com
Mon Jun 1 17:02:10 PDT 2015
> On 2015-May-29, at 11:15, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
>
>
>> On 2015-May-27, at 17:55, David Blaikie <dblaikie at gmail.com> wrote:
>>
>> Can't say I know of any particular situations that cause this (I guess it's trickier than just a variable that's optimized away entirely) - I'd just start reducing an existing test case (probably add the assertion and try a non-LTO build, hope that it reproduces there, then just creduce any specific file where it reproduces)
>>
>>> On Wed, May 27, 2015 at 5:51 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
>>> I've noticed there are debug loc lists with no entries sometimes
>>> in my heap profiling workload (a linker dump of `-flto -g`). It
>>> seems to happen when *all* the locations correspond to `%noreg`.
>>>
>>> This patch adds an assertion (which fires on my big workload,
>>> but not in any of our tests), and adds a likely fix that's
>>> commented out.
>>>
>>> Does anyone know how to generate this kind of thing, or should I
>>> just start compiling things to see if I can make it happen on my
>>> own? (I've tried reducing my workload, but I'm having trouble
>>> getting very far with it.)
Thanks Adrian and David for your pointers. In person, Adrian walked
me through how my original fix was insufficient: there are lots of
code paths that can produce empty .debug_loc entries. While the one
I avoided originally might be worth doing as a compile-time
optimization, the correct fix is to:
1. Finalize the entries that do exist. If an entry turns out to be
empty, delete it (pop_back()).
2. Once all entries have been finalized, check if the list has any
entries. If not, delete the list (pop_back()).
3. Delay creating a symbol and referring to the list until after
all its entries have been finalized.
The attached patches accomplish this:
- 0001: Refactor.
- 0002: Avoid empty .debug_loc lists. The testcase here is
actually fairly large, and I think the CHECK line is brittle. I
wonder if it would be better to combine this with 0003 and rely
only on the latter's testcase?
- 0003: Avoid empty .debug_loc list entries.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-AsmPrinter-Extract-DwarfDebug-createConcreteVariable.patch
Type: application/octet-stream
Size: 4063 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150601/ea2361a4/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-AsmPrinter-Don-t-emit-empty-.debug_loc-lists.patch
Type: application/octet-stream
Size: 16120 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150601/ea2361a4/attachment-0001.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-AsmPrinter-Don-t-emit-empty-.debug_loc-entries.patch
Type: application/octet-stream
Size: 6916 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150601/ea2361a4/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: all.patch
Type: application/octet-stream
Size: 23733 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150601/ea2361a4/attachment-0003.obj>
-------------- next part --------------
--
Besides these patches (but related):
David, you pointed out in some other thread that the objects to do
with DebugLocStream aren't particularly obvious anymore, and I
figure this makes it worse. Once some version of the attached
patches are in, I plan to (as a follow up) clean up the API here.
In particular, I think DebugLocStream should have iterators to walk
through lightweight ListProxy objects, which have iterators to walk
through lightweight EntryProxy objects. These would provide a nice
interface to DebugLocStream that made it look as if we had a simple
`vector<List:(entries: vector<Entry:(bytes: vector<char>)>)>` kind
of storage.
Furthermore, I suspect a Builder interface would clarify these
{start,finalize}{List,Entry}() functions, where the builders are
constructed by the "start" functions, and their destructors take
care of calling "finalize". For exposition, something like this:
// In collectVariableInfo():
DebugLocStream::ListBuilder LB = DebugLocs.startList(Asm, *this);
for (auto &E : Entries)
E.finalize(LB, ...);
// In DebugLocEntry::finalize():
DebugLocStream::EntryBuilder EB = LB.startEntry();
BufferByteStreamer Streamer = EB.getStreamer();
(0003 already does something like this for building the entries.)
Let me know what you guys think of this as well.
More information about the llvm-commits
mailing list