This is an archive of the discontinued LLVM Phabricator instance.

[DebugInfo] Add interface for pre-calculating the size of emitted DWARF
ClosedPublic

Authored by dstenb on Sep 19 2019, 9:06 AM.

Details

Summary

DWARF's DW_OP_entry_value operation has two operands; the first is a
ULEB128 operand that specifies the size of the second operand, which is
a DWARF block. This means that we need to be able to pre-calculate and
emit the size of DWARF expressions before emitting them. There is
currently no interface for doing this in DwarfExpression, so this patch
introduces that.

When implementing this I initially thought about running through
DwarfExpression's emission two times; first with a temporary buffer to
emit the expression, in order to being able to calculate the size of
that emitted data. However, DwarfExpression is a quite complex state
machine, so I decided against that, as it seemed like the two runs could
get out of sync, resulting in incorrect size operands. Therefore I have
implemented this in a way that we only have to run DwarfExpression once.
The idea is to emit DWARF to a temporary buffer, for which it is
possible to query the size. The data in the temporary buffer can then be
emitted to DwarfExpression's main output.

In the case of DIEDwarfExpression, a temporary DIE is used. The values
are all allocated using the same BumpPtrAllocator as for all other DIEs,
and the values are then transferred to the real value list. In the case
of DebugLocDwarfExpression, the temporary buffer is implemented using a
BufferByteStreamer which emits to a buffer in the DwarfExpression
object.

Diff Detail

Event Timeline

dstenb created this revision.Sep 19 2019, 9:06 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 19 2019, 9:06 AM
aprantl added inline comments.Sep 20 2019, 9:18 AM
llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
336

Since we have thousands of location list entries per file and DW_OP_entry_value is comparatively rare, should we make these heap- or tail-allocated (i.e. std::vector / unique_ptr)?

dstenb marked an inline comment as done.Sep 23 2019, 7:47 AM
dstenb added inline comments.
llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
336

That seems better! I built a clang 8.0 binary with -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_FLAGS="-Xclang -femit-debug-entry-values, and there only ~1.6% of DebugLocDwarfExpression objects needed to use the temporary buffer. As far as I understand we only have one DebugLocDwarfExpression object alive at a time, so the peak is not increased drastically, but it seems nasty to have to do unnecessary allocations/initializations for most of the objects. I'll dynamically allocate the data.

dstenb updated this revision to Diff 221332.Sep 23 2019, 7:49 AM

Dynamically allocate the temporary buffer in DebugLocDwarfExpression.

dstenb marked an inline comment as done.Oct 11 2019, 6:50 AM
aprantl accepted this revision.Oct 11 2019, 3:05 PM

lgtm with inline comments addressed

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
337

A SmallVector<std::string> doesn't seem to make that much sense, since strings are always heap-allocated. Either this should be a vector<string> or a SmallVector<SmallString>.

This revision is now accepted and ready to land.Oct 11 2019, 3:05 PM
dstenb marked an inline comment as done.Oct 14 2019, 1:19 PM
dstenb added inline comments.
llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
337

Good point!

I made this a SmallVector<std::string> as BufferByteStreamer expects that, so that is what is already used in DebugLocStream:

SmallString<256> DWARFBytes;    
SmallVector<std::string, 32> Comments;

However, when building a RelWithDebInfo clang-8 build, the average size of that Comments vector was actually around ~10000, so it seems that a small vector is not beneficial here (in addition to the issue with "allocating" std::strings on the stack as you point out). The size of DWARFBytes is the same as Comments, so perhaps they both should be std::vectors. If so, I'll do that change as a preparatory NFC commit.

Thanks!

Out of curiosity: do we record the comments even when we don't emit textual assembler? That sounds wasteful. Feel free to do any separate NFC refactorings to make these data structures more sensible.

Out of curiosity: do we record the comments even when we don't emit textual assembler?

Recording of comments is only done for textual assembly. It is enabled by querying MCStreamer::isVerbose(), which always returns false in the object file implementation.

(I used -save-temps when measuring the average size.)

dstenb updated this revision to Diff 224995.Oct 15 2019, 4:02 AM

Rebase (to make Comments a std::vector<std::string>.

This revision was automatically updated to reflect the committed changes.