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

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 28 16:14:09 PDT 2019


On Tue, Oct 15, 2019 at 4:12 AM David Stenberg via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: dstenb
> Date: Tue Oct 15 04:14:35 2019
> New Revision: 374879
>
> URL: http://llvm.org/viewvc/llvm-project?rev=374879&view=rev
> Log:
> [DebugInfo] Add interface for pre-calculating the size of emitted DWARF
>
> 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.


"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?


> In the case
> of DebugLocDwarfExpression, the temporary buffer is implemented using a
> BufferByteStreamer which emits to a buffer in the DwarfExpression
> object.
>
> Reviewers: aprantl, vsk, NikolaPrica, djtodoro
>
> Reviewed By: aprantl
>
> Subscribers: hiraditya, llvm-commits
>
> Tags: #debug-info, #llvm
>
> Differential Revision: https://reviews.llvm.org/D67768
>
> Modified:
>     llvm/trunk/include/llvm/CodeGen/DIE.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
>
> Modified: llvm/trunk/include/llvm/CodeGen/DIE.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DIE.h?rev=374879&r1=374878&r2=374879&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/DIE.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/DIE.h Tue Oct 15 04:14:35 2019
> @@ -550,6 +550,14 @@ public:
>      return *static_cast<T *>(Last ? Last->Next.getPointer() : nullptr);
>    }
>
> +  void takeNodes(IntrusiveBackList<T> &Other) {
> +    for (auto &N : Other) {
> +      N.Next.setPointerAndInt(&N, true);
> +      push_back(N);
> +    }
> +    Other.Last = nullptr;
> +  }
> +
>    class const_iterator;
>    class iterator
>        : public iterator_facade_base<iterator, std::forward_iterator_tag,
> T> {
> @@ -685,6 +693,10 @@ public:
>      return addValue(Alloc, DIEValue(Attribute, Form,
> std::forward<T>(Value)));
>    }
>
> +  /// Take ownership of the nodes in \p Other, and append them to the
> back of
> +  /// the list.
> +  void takeValues(DIEValueList &Other) { List.takeNodes(Other.List); }
> +
>    value_range values() {
>      return make_range(value_iterator(List.begin()),
> value_iterator(List.end()));
>    }
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h?rev=374879&r1=374878&r2=374879&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/ByteStreamer.h Tue Oct 15 04:14:35
> 2019
> @@ -75,16 +75,16 @@ private:
>    SmallVectorImpl<char> &Buffer;
>    std::vector<std::string> &Comments;
>
> +public:
>    /// Only verbose textual output needs comments.  This will be set to
>    /// true for that case, and false otherwise.  If false, comments passed
> in to
>    /// the emit methods will be ignored.
> -  bool GenerateComments;
> +  const bool GenerateComments;
>
> -public:
>    BufferByteStreamer(SmallVectorImpl<char> &Buffer,
> -                     std::vector<std::string> &Comments,
> -                     bool GenerateComments)
> -  : Buffer(Buffer), Comments(Comments),
> GenerateComments(GenerateComments) {}
> +                     std::vector<std::string> &Comments, bool
> GenerateComments)
> +      : Buffer(Buffer), Comments(Comments),
> GenerateComments(GenerateComments) {
> +  }
>    void EmitInt8(uint8_t Byte, const Twine &Comment) override {
>      Buffer.push_back(Byte);
>      if (GenerateComments)
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=374879&r1=374878&r2=374879&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Oct 15 04:14:35
> 2019
> @@ -170,26 +170,26 @@ static const char *const DbgTimerDescrip
>  static constexpr unsigned ULEB128PadSize = 4;
>
>  void DebugLocDwarfExpression::emitOp(uint8_t Op, const char *Comment) {
> -  BS.EmitInt8(
> +  getActiveStreamer().EmitInt8(
>        Op, Comment ? Twine(Comment) + " " +
> dwarf::OperationEncodingString(Op)
>                    : dwarf::OperationEncodingString(Op));
>  }
>
>  void DebugLocDwarfExpression::emitSigned(int64_t Value) {
> -  BS.EmitSLEB128(Value, Twine(Value));
> +  getActiveStreamer().EmitSLEB128(Value, Twine(Value));
>  }
>
>  void DebugLocDwarfExpression::emitUnsigned(uint64_t Value) {
> -  BS.EmitULEB128(Value, Twine(Value));
> +  getActiveStreamer().EmitULEB128(Value, Twine(Value));
>  }
>
>  void DebugLocDwarfExpression::emitData1(uint8_t Value) {
> -  BS.EmitInt8(Value, Twine(Value));
> +  getActiveStreamer().EmitInt8(Value, Twine(Value));
>  }
>
>  void DebugLocDwarfExpression::emitBaseTypeRef(uint64_t Idx) {
>    assert(Idx < (1ULL << (ULEB128PadSize * 7)) && "Idx wont fit");
> -  BS.EmitULEB128(Idx, Twine(Idx), ULEB128PadSize);
> +  getActiveStreamer().EmitULEB128(Idx, Twine(Idx), ULEB128PadSize);
>  }
>
>  bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo
> &TRI,
> @@ -198,6 +198,32 @@ bool DebugLocDwarfExpression::isFrameReg
>    return false;
>  }
>
> +void DebugLocDwarfExpression::enableTemporaryBuffer() {
> +  assert(!IsBuffering && "Already buffering?");
> +  if (!TmpBuf)
> +    TmpBuf = std::make_unique<TempBuffer>(OutBS.GenerateComments);
> +  IsBuffering = true;
> +}
> +
> +void DebugLocDwarfExpression::disableTemporaryBuffer() { IsBuffering =
> false; }
> +
> +unsigned DebugLocDwarfExpression::getTemporaryBufferSize() {
> +  return TmpBuf ? TmpBuf->Bytes.size() : 0;
> +}
> +
> +void DebugLocDwarfExpression::commitTemporaryBuffer() {
> +  if (!TmpBuf)
> +    return;
> +  for (auto Byte : enumerate(TmpBuf->Bytes)) {
> +    const char *Comment = (Byte.index() < TmpBuf->Comments.size())
> +                              ? TmpBuf->Comments[Byte.index()].c_str()
> +                              : "";
> +    OutBS.EmitInt8(Byte.value(), Comment);
> +  }
> +  TmpBuf->Bytes.clear();
> +  TmpBuf->Comments.clear();
> +}
> +
>  const DIType *DbgVariable::getType() const {
>    return getVariable()->getType();
>  }
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=374879&r1=374878&r2=374879&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h Tue Oct 15
> 04:14:35 2019
> @@ -13,6 +13,7 @@
>  #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
>  #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
>
> +#include "ByteStreamer.h"
>  #include "llvm/ADT/ArrayRef.h"
>  #include "llvm/ADT/None.h"
>  #include "llvm/ADT/Optional.h"
> @@ -26,7 +27,6 @@ namespace llvm {
>
>  class AsmPrinter;
>  class APInt;
> -class ByteStreamer;
>  class DwarfCompileUnit;
>  class DIELoc;
>  class TargetRegisterInfo;
> @@ -95,6 +95,13 @@ public:
>  /// Base class containing the logic for constructing DWARF expressions
>  /// independently of whether they are emitted into a DIE or into a
> .debug_loc
>  /// entry.
> +///
> +/// Some DWARF operations, e.g. DW_OP_entry_value, need to calculate the
> size
> +/// of a succeeding DWARF block before the latter is emitted to the
> output.
> +/// To handle such cases, data can conditionally be emitted to a temporary
> +/// buffer, which can later on be committed to the main output. The size
> of the
> +/// temporary buffer is queryable, allowing for the size of the data to be
> +/// emitted before the data is committed.
>  class DwarfExpression {
>  protected:
>    /// Holds information about all subregisters comprising a register
> location.
> @@ -178,6 +185,22 @@ protected:
>
>    virtual void emitBaseTypeRef(uint64_t Idx) = 0;
>
> +  /// Start emitting data to the temporary buffer. The data stored in the
> +  /// temporary buffer can be committed to the main output using
> +  /// commitTemporaryBuffer().
> +  virtual void enableTemporaryBuffer() = 0;
> +
> +  /// Disable emission to the temporary buffer. This does not commit data
> +  /// in the temporary buffer to the main output.
> +  virtual void disableTemporaryBuffer() = 0;
> +
> +  /// Return the emitted size, in number of bytes, for the data stored in
> the
> +  /// temporary buffer.
> +  virtual unsigned getTemporaryBufferSize() = 0;
> +
> +  /// Commit the data stored in the temporary buffer to the main output.
> +  virtual void commitTemporaryBuffer() = 0;
> +
>    /// Emit a normalized unsigned constant.
>    void emitConstu(uint64_t Value);
>
> @@ -308,31 +331,62 @@ public:
>
>  /// DwarfExpression implementation for .debug_loc entries.
>  class DebugLocDwarfExpression final : public DwarfExpression {
> -  ByteStreamer &BS;
> +
> +  struct TempBuffer {
> +    SmallString<32> Bytes;
> +    std::vector<std::string> Comments;
> +    BufferByteStreamer BS;
> +
> +    TempBuffer(bool GenerateComments) : BS(Bytes, Comments,
> GenerateComments) {}
> +  };
> +
> +  std::unique_ptr<TempBuffer> TmpBuf;
> +  BufferByteStreamer &OutBS;
> +  bool IsBuffering = false;
> +
> +  /// Return the byte streamer that currently is being emitted to.
> +  ByteStreamer &getActiveStreamer() { return IsBuffering ? TmpBuf->BS :
> OutBS; }
>
>    void emitOp(uint8_t Op, const char *Comment = nullptr) override;
>    void emitSigned(int64_t Value) override;
>    void emitUnsigned(uint64_t Value) override;
>    void emitData1(uint8_t Value) override;
>    void emitBaseTypeRef(uint64_t Idx) override;
> +
> +  void enableTemporaryBuffer() override;
> +  void disableTemporaryBuffer() override;
> +  unsigned getTemporaryBufferSize() override;
> +  void commitTemporaryBuffer() override;
> +
>    bool isFrameRegister(const TargetRegisterInfo &TRI,
>                         unsigned MachineReg) override;
> -
>  public:
> -  DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS,
> DwarfCompileUnit &CU)
> -      : DwarfExpression(DwarfVersion, CU), BS(BS) {}
> +  DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS,
> +                          DwarfCompileUnit &CU)
> +      : DwarfExpression(DwarfVersion, CU), OutBS(BS) {}
>  };
>
>  /// DwarfExpression implementation for singular DW_AT_location.
>  class DIEDwarfExpression final : public DwarfExpression {
> -const AsmPrinter &AP;
> -  DIELoc &DIE;
> +  const AsmPrinter &AP;
> +  DIELoc &OutDIE;
> +  DIELoc TmpDIE;
> +  bool IsBuffering = false;
> +
> +  /// Return the DIE that currently is being emitted to.
> +  DIELoc &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; }
>
>    void emitOp(uint8_t Op, const char *Comment = nullptr) override;
>    void emitSigned(int64_t Value) override;
>    void emitUnsigned(uint64_t Value) override;
>    void emitData1(uint8_t Value) override;
>    void emitBaseTypeRef(uint64_t Idx) override;
> +
> +  void enableTemporaryBuffer() override;
> +  void disableTemporaryBuffer() override;
> +  unsigned getTemporaryBufferSize() override;
> +  void commitTemporaryBuffer() override;
> +
>    bool isFrameRegister(const TargetRegisterInfo &TRI,
>                         unsigned MachineReg) override;
>  public:
> @@ -340,7 +394,7 @@ public:
>
>    DIELoc *finalize() {
>      DwarfExpression::finalize();
> -    return &DIE;
> +    return &OutDIE;
>    }
>  };
>
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=374879&r1=374878&r2=374879&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Tue Oct 15 04:14:35
> 2019
> @@ -47,31 +47,42 @@ using namespace llvm;
>  #define DEBUG_TYPE "dwarfdebug"
>
>  DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP,
> -                                       DwarfCompileUnit &CU,
> -                                       DIELoc &DIE)
> -    : DwarfExpression(AP.getDwarfVersion(), CU), AP(AP),
> -      DIE(DIE) {}
> +                                       DwarfCompileUnit &CU, DIELoc &DIE)
> +    : DwarfExpression(AP.getDwarfVersion(), CU), AP(AP), OutDIE(DIE) {}
>
>  void DIEDwarfExpression::emitOp(uint8_t Op, const char* Comment) {
> -  CU.addUInt(DIE, dwarf::DW_FORM_data1, Op);
> +  CU.addUInt(getActiveDIE(), dwarf::DW_FORM_data1, Op);
>  }
>
>  void DIEDwarfExpression::emitSigned(int64_t Value) {
> -  CU.addSInt(DIE, dwarf::DW_FORM_sdata, Value);
> +  CU.addSInt(getActiveDIE(), dwarf::DW_FORM_sdata, Value);
>  }
>
>  void DIEDwarfExpression::emitUnsigned(uint64_t Value) {
> -  CU.addUInt(DIE, dwarf::DW_FORM_udata, Value);
> +  CU.addUInt(getActiveDIE(), dwarf::DW_FORM_udata, Value);
>  }
>
>  void DIEDwarfExpression::emitData1(uint8_t Value) {
> -  CU.addUInt(DIE, dwarf::DW_FORM_data1, Value);
> +  CU.addUInt(getActiveDIE(), dwarf::DW_FORM_data1, Value);
>  }
>
>  void DIEDwarfExpression::emitBaseTypeRef(uint64_t Idx) {
> -  CU.addBaseTypeRef(DIE, Idx);
> +  CU.addBaseTypeRef(getActiveDIE(), Idx);
>  }
>
> +void DIEDwarfExpression::enableTemporaryBuffer() {
> +  assert(!IsBuffering && "Already buffering?");
> +  IsBuffering = true;
> +}
> +
> +void DIEDwarfExpression::disableTemporaryBuffer() { IsBuffering = false; }
> +
> +unsigned DIEDwarfExpression::getTemporaryBufferSize() {
> +  return TmpDIE.ComputeSize(&AP);
> +}
> +
> +void DIEDwarfExpression::commitTemporaryBuffer() {
> OutDIE.takeValues(TmpDIE); }
> +
>  bool DIEDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,
>                                           unsigned MachineReg) {
>    return MachineReg == TRI.getFrameRegister(*AP.MF);
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191028/b3af24ec/attachment.html>


More information about the llvm-commits mailing list