<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 15, 2019 at 4:12 AM David Stenberg via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: dstenb<br>
Date: Tue Oct 15 04:14:35 2019<br>
New Revision: 374879<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=374879&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=374879&view=rev</a><br>
Log:<br>
[DebugInfo] Add interface for pre-calculating the size of emitted DWARF<br>
<br>
Summary:<br>
DWARF's DW_OP_entry_value operation has two operands; the first is a<br>
ULEB128 operand that specifies the size of the second operand, which is<br>
a DWARF block. This means that we need to be able to pre-calculate and<br>
emit the size of DWARF expressions before emitting them. There is<br>
currently no interface for doing this in DwarfExpression, so this patch<br>
introduces that.<br>
<br>
When implementing this I initially thought about running through<br>
DwarfExpression's emission two times; first with a temporary buffer to<br>
emit the expression, in order to being able to calculate the size of<br>
that emitted data. However, DwarfExpression is a quite complex state<br>
machine, so I decided against that, as it seemed like the two runs could<br>
get out of sync, resulting in incorrect size operands. Therefore I have<br>
implemented this in a way that we only have to run DwarfExpression once.<br>
The idea is to emit DWARF to a temporary buffer, for which it is<br>
possible to query the size. The data in the temporary buffer can then be<br>
emitted to DwarfExpression's main output.<br>
<br>
In the case of DIEDwarfExpression, a temporary DIE is used. The values<br>
are all allocated using the same BumpPtrAllocator as for all other DIEs,<br>
and the values are then transferred to the real value list.</blockquote><div><br>"temporary" and "BumpPtrAllocator" are a bit antithetical - this produces a sort of reachable memory leak? Should that be revisited/maybe a different allocation scheme used?<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> In the case<br>
of DebugLocDwarfExpression, the temporary buffer is implemented using a<br>
BufferByteStreamer which emits to a buffer in the DwarfExpression<br>
object.<br>
<br>
Reviewers: aprantl, vsk, NikolaPrica, djtodoro<br>
<br>
Reviewed By: aprantl<br>
<br>
Subscribers: hiraditya, llvm-commits<br>
<br>
Tags: #debug-info, #llvm<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D67768" rel="noreferrer" target="_blank">https://reviews.llvm.org/D67768</a><br>
<br>
Modified:<br>
llvm/trunk/include/llvm/CodeGen/DIE.h<br>
llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h<br>
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h<br>
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGen/DIE.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DIE.h?rev=374879&r1=374878&r2=374879&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DIE.h?rev=374879&r1=374878&r2=374879&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/DIE.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGen/DIE.h Tue Oct 15 04:14:35 2019<br>
@@ -550,6 +550,14 @@ public:<br>
return *static_cast<T *>(Last ? Last->Next.getPointer() : nullptr);<br>
}<br>
<br>
+ void takeNodes(IntrusiveBackList<T> &Other) {<br>
+ for (auto &N : Other) {<br>
+ N.Next.setPointerAndInt(&N, true);<br>
+ push_back(N);<br>
+ }<br>
+ Other.Last = nullptr;<br>
+ }<br>
+<br>
class const_iterator;<br>
class iterator<br>
: public iterator_facade_base<iterator, std::forward_iterator_tag, T> {<br>
@@ -685,6 +693,10 @@ public:<br>
return addValue(Alloc, DIEValue(Attribute, Form, std::forward<T>(Value)));<br>
}<br>
<br>
+ /// Take ownership of the nodes in \p Other, and append them to the back of<br>
+ /// the list.<br>
+ void takeValues(DIEValueList &Other) { List.takeNodes(Other.List); }<br>
+<br>
value_range values() {<br>
return make_range(value_iterator(List.begin()), value_iterator(List.end()));<br>
}<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h?rev=374879&r1=374878&r2=374879&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h?rev=374879&r1=374878&r2=374879&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h Tue Oct 15 04:14:35 2019<br>
@@ -75,16 +75,16 @@ private:<br>
SmallVectorImpl<char> &Buffer;<br>
std::vector<std::string> &Comments;<br>
<br>
+public:<br>
/// Only verbose textual output needs comments. This will be set to<br>
/// true for that case, and false otherwise. If false, comments passed in to<br>
/// the emit methods will be ignored.<br>
- bool GenerateComments;<br>
+ const bool GenerateComments;<br>
<br>
-public:<br>
BufferByteStreamer(SmallVectorImpl<char> &Buffer,<br>
- std::vector<std::string> &Comments,<br>
- bool GenerateComments)<br>
- : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) {}<br>
+ std::vector<std::string> &Comments, bool GenerateComments)<br>
+ : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) {<br>
+ }<br>
void EmitInt8(uint8_t Byte, const Twine &Comment) override {<br>
Buffer.push_back(Byte);<br>
if (GenerateComments)<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=374879&r1=374878&r2=374879&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=374879&r1=374878&r2=374879&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Oct 15 04:14:35 2019<br>
@@ -170,26 +170,26 @@ static const char *const DbgTimerDescrip<br>
static constexpr unsigned ULEB128PadSize = 4;<br>
<br>
void DebugLocDwarfExpression::emitOp(uint8_t Op, const char *Comment) {<br>
- BS.EmitInt8(<br>
+ getActiveStreamer().EmitInt8(<br>
Op, Comment ? Twine(Comment) + " " + dwarf::OperationEncodingString(Op)<br>
: dwarf::OperationEncodingString(Op));<br>
}<br>
<br>
void DebugLocDwarfExpression::emitSigned(int64_t Value) {<br>
- BS.EmitSLEB128(Value, Twine(Value));<br>
+ getActiveStreamer().EmitSLEB128(Value, Twine(Value));<br>
}<br>
<br>
void DebugLocDwarfExpression::emitUnsigned(uint64_t Value) {<br>
- BS.EmitULEB128(Value, Twine(Value));<br>
+ getActiveStreamer().EmitULEB128(Value, Twine(Value));<br>
}<br>
<br>
void DebugLocDwarfExpression::emitData1(uint8_t Value) {<br>
- BS.EmitInt8(Value, Twine(Value));<br>
+ getActiveStreamer().EmitInt8(Value, Twine(Value));<br>
}<br>
<br>
void DebugLocDwarfExpression::emitBaseTypeRef(uint64_t Idx) {<br>
assert(Idx < (1ULL << (ULEB128PadSize * 7)) && "Idx wont fit");<br>
- BS.EmitULEB128(Idx, Twine(Idx), ULEB128PadSize);<br>
+ getActiveStreamer().EmitULEB128(Idx, Twine(Idx), ULEB128PadSize);<br>
}<br>
<br>
bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,<br>
@@ -198,6 +198,32 @@ bool DebugLocDwarfExpression::isFrameReg<br>
return false;<br>
}<br>
<br>
+void DebugLocDwarfExpression::enableTemporaryBuffer() {<br>
+ assert(!IsBuffering && "Already buffering?");<br>
+ if (!TmpBuf)<br>
+ TmpBuf = std::make_unique<TempBuffer>(OutBS.GenerateComments);<br>
+ IsBuffering = true;<br>
+}<br>
+<br>
+void DebugLocDwarfExpression::disableTemporaryBuffer() { IsBuffering = false; }<br>
+<br>
+unsigned DebugLocDwarfExpression::getTemporaryBufferSize() {<br>
+ return TmpBuf ? TmpBuf->Bytes.size() : 0;<br>
+}<br>
+<br>
+void DebugLocDwarfExpression::commitTemporaryBuffer() {<br>
+ if (!TmpBuf)<br>
+ return;<br>
+ for (auto Byte : enumerate(TmpBuf->Bytes)) {<br>
+ const char *Comment = (Byte.index() < TmpBuf->Comments.size())<br>
+ ? TmpBuf->Comments[Byte.index()].c_str()<br>
+ : "";<br>
+ OutBS.EmitInt8(Byte.value(), Comment);<br>
+ }<br>
+ TmpBuf->Bytes.clear();<br>
+ TmpBuf->Comments.clear();<br>
+}<br>
+<br>
const DIType *DbgVariable::getType() const {<br>
return getVariable()->getType();<br>
}<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=374879&r1=374878&r2=374879&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=374879&r1=374878&r2=374879&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h Tue Oct 15 04:14:35 2019<br>
@@ -13,6 +13,7 @@<br>
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H<br>
#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H<br>
<br>
+#include "ByteStreamer.h"<br>
#include "llvm/ADT/ArrayRef.h"<br>
#include "llvm/ADT/None.h"<br>
#include "llvm/ADT/Optional.h"<br>
@@ -26,7 +27,6 @@ namespace llvm {<br>
<br>
class AsmPrinter;<br>
class APInt;<br>
-class ByteStreamer;<br>
class DwarfCompileUnit;<br>
class DIELoc;<br>
class TargetRegisterInfo;<br>
@@ -95,6 +95,13 @@ public:<br>
/// Base class containing the logic for constructing DWARF expressions<br>
/// independently of whether they are emitted into a DIE or into a .debug_loc<br>
/// entry.<br>
+///<br>
+/// Some DWARF operations, e.g. DW_OP_entry_value, need to calculate the size<br>
+/// of a succeeding DWARF block before the latter is emitted to the output.<br>
+/// To handle such cases, data can conditionally be emitted to a temporary<br>
+/// buffer, which can later on be committed to the main output. The size of the<br>
+/// temporary buffer is queryable, allowing for the size of the data to be<br>
+/// emitted before the data is committed.<br>
class DwarfExpression {<br>
protected:<br>
/// Holds information about all subregisters comprising a register location.<br>
@@ -178,6 +185,22 @@ protected:<br>
<br>
virtual void emitBaseTypeRef(uint64_t Idx) = 0;<br>
<br>
+ /// Start emitting data to the temporary buffer. The data stored in the<br>
+ /// temporary buffer can be committed to the main output using<br>
+ /// commitTemporaryBuffer().<br>
+ virtual void enableTemporaryBuffer() = 0;<br>
+<br>
+ /// Disable emission to the temporary buffer. This does not commit data<br>
+ /// in the temporary buffer to the main output.<br>
+ virtual void disableTemporaryBuffer() = 0;<br>
+<br>
+ /// Return the emitted size, in number of bytes, for the data stored in the<br>
+ /// temporary buffer.<br>
+ virtual unsigned getTemporaryBufferSize() = 0;<br>
+<br>
+ /// Commit the data stored in the temporary buffer to the main output.<br>
+ virtual void commitTemporaryBuffer() = 0;<br>
+<br>
/// Emit a normalized unsigned constant.<br>
void emitConstu(uint64_t Value);<br>
<br>
@@ -308,31 +331,62 @@ public:<br>
<br>
/// DwarfExpression implementation for .debug_loc entries.<br>
class DebugLocDwarfExpression final : public DwarfExpression {<br>
- ByteStreamer &BS;<br>
+<br>
+ struct TempBuffer {<br>
+ SmallString<32> Bytes;<br>
+ std::vector<std::string> Comments;<br>
+ BufferByteStreamer BS;<br>
+<br>
+ TempBuffer(bool GenerateComments) : BS(Bytes, Comments, GenerateComments) {}<br>
+ };<br>
+<br>
+ std::unique_ptr<TempBuffer> TmpBuf;<br>
+ BufferByteStreamer &OutBS;<br>
+ bool IsBuffering = false;<br>
+<br>
+ /// Return the byte streamer that currently is being emitted to.<br>
+ ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS : OutBS; }<br>
<br>
void emitOp(uint8_t Op, const char *Comment = nullptr) override;<br>
void emitSigned(int64_t Value) override;<br>
void emitUnsigned(uint64_t Value) override;<br>
void emitData1(uint8_t Value) override;<br>
void emitBaseTypeRef(uint64_t Idx) override;<br>
+<br>
+ void enableTemporaryBuffer() override;<br>
+ void disableTemporaryBuffer() override;<br>
+ unsigned getTemporaryBufferSize() override;<br>
+ void commitTemporaryBuffer() override;<br>
+<br>
bool isFrameRegister(const TargetRegisterInfo &TRI,<br>
unsigned MachineReg) override;<br>
-<br>
public:<br>
- DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS, DwarfCompileUnit &CU)<br>
- : DwarfExpression(DwarfVersion, CU), BS(BS) {}<br>
+ DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS,<br>
+ DwarfCompileUnit &CU)<br>
+ : DwarfExpression(DwarfVersion, CU), OutBS(BS) {}<br>
};<br>
<br>
/// DwarfExpression implementation for singular DW_AT_location.<br>
class DIEDwarfExpression final : public DwarfExpression {<br>
-const AsmPrinter &AP;<br>
- DIELoc &DIE;<br>
+ const AsmPrinter &AP;<br>
+ DIELoc &OutDIE;<br>
+ DIELoc TmpDIE;<br>
+ bool IsBuffering = false;<br>
+<br>
+ /// Return the DIE that currently is being emitted to.<br>
+ DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; }<br>
<br>
void emitOp(uint8_t Op, const char *Comment = nullptr) override;<br>
void emitSigned(int64_t Value) override;<br>
void emitUnsigned(uint64_t Value) override;<br>
void emitData1(uint8_t Value) override;<br>
void emitBaseTypeRef(uint64_t Idx) override;<br>
+<br>
+ void enableTemporaryBuffer() override;<br>
+ void disableTemporaryBuffer() override;<br>
+ unsigned getTemporaryBufferSize() override;<br>
+ void commitTemporaryBuffer() override;<br>
+<br>
bool isFrameRegister(const TargetRegisterInfo &TRI,<br>
unsigned MachineReg) override;<br>
public:<br>
@@ -340,7 +394,7 @@ public:<br>
<br>
DIELoc *finalize() {<br>
DwarfExpression::finalize();<br>
- return &DIE;<br>
+ return &OutDIE;<br>
}<br>
};<br>
<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=374879&r1=374878&r2=374879&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=374879&r1=374878&r2=374879&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Tue Oct 15 04:14:35 2019<br>
@@ -47,31 +47,42 @@ using namespace llvm;<br>
#define DEBUG_TYPE "dwarfdebug"<br>
<br>
DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP,<br>
- DwarfCompileUnit &CU,<br>
- DIELoc &DIE)<br>
- : DwarfExpression(AP.getDwarfVersion(), CU), AP(AP),<br>
- DIE(DIE) {}<br>
+ DwarfCompileUnit &CU, DIELoc &DIE)<br>
+ : DwarfExpression(AP.getDwarfVersion(), CU), AP(AP), OutDIE(DIE) {}<br>
<br>
void DIEDwarfExpression::emitOp(uint8_t Op, const char* Comment) {<br>
- CU.addUInt(DIE, dwarf::DW_FORM_data1, Op);<br>
+ CU.addUInt(getActiveDIE(), dwarf::DW_FORM_data1, Op);<br>
}<br>
<br>
void DIEDwarfExpression::emitSigned(int64_t Value) {<br>
- CU.addSInt(DIE, dwarf::DW_FORM_sdata, Value);<br>
+ CU.addSInt(getActiveDIE(), dwarf::DW_FORM_sdata, Value);<br>
}<br>
<br>
void DIEDwarfExpression::emitUnsigned(uint64_t Value) {<br>
- CU.addUInt(DIE, dwarf::DW_FORM_udata, Value);<br>
+ CU.addUInt(getActiveDIE(), dwarf::DW_FORM_udata, Value);<br>
}<br>
<br>
void DIEDwarfExpression::emitData1(uint8_t Value) {<br>
- CU.addUInt(DIE, dwarf::DW_FORM_data1, Value);<br>
+ CU.addUInt(getActiveDIE(), dwarf::DW_FORM_data1, Value);<br>
}<br>
<br>
void DIEDwarfExpression::emitBaseTypeRef(uint64_t Idx) {<br>
- CU.addBaseTypeRef(DIE, Idx);<br>
+ CU.addBaseTypeRef(getActiveDIE(), Idx);<br>
}<br>
<br>
+void DIEDwarfExpression::enableTemporaryBuffer() {<br>
+ assert(!IsBuffering && "Already buffering?");<br>
+ IsBuffering = true;<br>
+}<br>
+<br>
+void DIEDwarfExpression::disableTemporaryBuffer() { IsBuffering = false; }<br>
+<br>
+unsigned DIEDwarfExpression::getTemporaryBufferSize() {<br>
+ return TmpDIE.ComputeSize(&AP);<br>
+}<br>
+<br>
+void DIEDwarfExpression::commitTemporaryBuffer() { OutDIE.takeValues(TmpDIE); }<br>
+<br>
bool DIEDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,<br>
unsigned MachineReg) {<br>
return MachineReg == TRI.getFrameRegister(*AP.MF);<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>