From 342ebd445bb3dae8b0c119a6126a318ad378a377 Mon Sep 17 00:00:00 2001 From: PJ Reiniger Date: Sun, 8 May 2022 13:48:59 -0400 Subject: [PATCH 12/28] Add vectors to raw_ostream --- llvm/include/llvm/Support/raw_ostream.h | 115 ++++++++++++++++++++++++ llvm/lib/Support/raw_ostream.cpp | 47 ++++++++++ 2 files changed, 162 insertions(+) diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h index d4521c8e2..bf5630ab5 100644 --- a/llvm/include/llvm/Support/raw_ostream.h +++ b/llvm/include/llvm/Support/raw_ostream.h @@ -25,6 +25,7 @@ #endif #include #include +#include namespace llvm { @@ -248,12 +249,24 @@ public: return write(Str.data(), Str.size()); } + raw_ostream &operator<<(const std::vector &Arr) { + // Avoid the fast path, it would only increase code size for a marginal win. + return write(Arr.data(), Arr.size()); + } + + raw_ostream &operator<<(const SmallVectorImpl &Arr) { + return write(Arr.data(), Arr.size()); + } + /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't /// satisfy llvm::isPrint into an escape sequence. raw_ostream &write_escaped(std::string_view Str, bool UseHexEscapes = false); raw_ostream &write(unsigned char C); raw_ostream &write(const char *Ptr, size_t Size); + raw_ostream &write(const uint8_t *Ptr, size_t Size) { + return write(reinterpret_cast(Ptr), Size); + } /// indent - Insert 'NumSpaces' spaces. raw_ostream &indent(unsigned NumSpaces); @@ -604,6 +617,108 @@ public: } }; +/// A raw_ostream that writes to a vector. This is a +/// simple adaptor class. This class does not encounter output errors. +/// raw_vector_ostream operates without a buffer, delegating all memory +/// management to the vector. Thus the vector is always up-to-date, +/// may be used directly and there is no need to call flush(). +class raw_vector_ostream : public raw_pwrite_stream { + std::vector &OS; + + /// See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t Size) override; + + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream. + uint64_t current_pos() const override; + +public: + /// Construct a new raw_svector_ostream. + /// + /// \param O The vector to write to; this should generally have at least 128 + /// bytes free to avoid any extraneous memory overhead. + explicit raw_vector_ostream(std::vector &O) : OS(O) { + SetUnbuffered(); + } + + ~raw_vector_ostream() override = default; + + void flush() = delete; + + /// Return a std::string_view for the vector contents. + std::string_view str() { return std::string_view(OS.data(), OS.size()); } +}; + +/// A raw_ostream that writes to an SmallVector or SmallString. This is a +/// simple adaptor class. This class does not encounter output errors. +/// raw_svector_ostream operates without a buffer, delegating all memory +/// management to the SmallString. Thus the SmallString is always up-to-date, +/// may be used directly and there is no need to call flush(). +class raw_usvector_ostream : public raw_pwrite_stream { + SmallVectorImpl &OS; + + /// See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t Size) override; + + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream. + uint64_t current_pos() const override; + +public: + /// Construct a new raw_svector_ostream. + /// + /// \param O The vector to write to; this should generally have at least 128 + /// bytes free to avoid any extraneous memory overhead. + explicit raw_usvector_ostream(SmallVectorImpl &O) : OS(O) { + SetUnbuffered(); + } + + ~raw_usvector_ostream() override = default; + + void flush() = delete; + + /// Return an span for the vector contents. + span array() { return {OS.data(), OS.size()}; } + span array() const { return {OS.data(), OS.size()}; } +}; + +/// A raw_ostream that writes to a vector. This is a +/// simple adaptor class. This class does not encounter output errors. +/// raw_vector_ostream operates without a buffer, delegating all memory +/// management to the vector. Thus the vector is always up-to-date, +/// may be used directly and there is no need to call flush(). +class raw_uvector_ostream : public raw_pwrite_stream { + std::vector &OS; + + /// See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t Size) override; + + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream. + uint64_t current_pos() const override; + +public: + /// Construct a new raw_svector_ostream. + /// + /// \param O The vector to write to; this should generally have at least 128 + /// bytes free to avoid any extraneous memory overhead. + explicit raw_uvector_ostream(std::vector &O) : OS(O) { + SetUnbuffered(); + } + + ~raw_uvector_ostream() override = default; + + void flush() = delete; + + /// Return a span for the vector contents. + span array() { return {OS.data(), OS.size()}; } + span array() const { return {OS.data(), OS.size()}; } +}; + + /// A raw_ostream that discards all output. class raw_null_ostream : public raw_pwrite_stream { /// See raw_ostream::write_impl. diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index 875eda7ba..36faf744c 100644 --- a/llvm/lib/Support/raw_ostream.cpp +++ b/llvm/lib/Support/raw_ostream.cpp @@ -658,6 +658,53 @@ void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size, memcpy(OS.data() + Offset, Ptr, Size); } +//===----------------------------------------------------------------------===// +// raw_vector_ostream +//===----------------------------------------------------------------------===// + +uint64_t raw_vector_ostream::current_pos() const { return OS.size(); } + +void raw_vector_ostream::write_impl(const char *Ptr, size_t Size) { + OS.insert(OS.end(), Ptr, Ptr + Size); +} + +void raw_vector_ostream::pwrite_impl(const char *Ptr, size_t Size, + uint64_t Offset) { + memcpy(OS.data() + Offset, Ptr, Size); +} + +//===----------------------------------------------------------------------===// +// raw_usvector_ostream +//===----------------------------------------------------------------------===// + +uint64_t raw_usvector_ostream::current_pos() const { return OS.size(); } + +void raw_usvector_ostream::write_impl(const char *Ptr, size_t Size) { + OS.append(reinterpret_cast(Ptr), + reinterpret_cast(Ptr) + Size); +} + +void raw_usvector_ostream::pwrite_impl(const char *Ptr, size_t Size, + uint64_t Offset) { + memcpy(OS.data() + Offset, Ptr, Size); +} + +//===----------------------------------------------------------------------===// +// raw_uvector_ostream +//===----------------------------------------------------------------------===// + +uint64_t raw_uvector_ostream::current_pos() const { return OS.size(); } + +void raw_uvector_ostream::write_impl(const char *Ptr, size_t Size) { + OS.insert(OS.end(), reinterpret_cast(Ptr), + reinterpret_cast(Ptr) + Size); +} + +void raw_uvector_ostream::pwrite_impl(const char *Ptr, size_t Size, + uint64_t Offset) { + memcpy(OS.data() + Offset, Ptr, Size); +} + //===----------------------------------------------------------------------===// // raw_null_ostream //===----------------------------------------------------------------------===//