[clang] [Support] Add VirtualOutputBackends to virtualize the output from tools (PR #68447)

Steven Wu via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 9 14:43:01 PDT 2023


================
@@ -0,0 +1,158 @@
+//===- raw_ostream_proxy.h - Proxies for raw output streams -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RAW_OSTREAM_PROXY_H
+#define LLVM_SUPPORT_RAW_OSTREAM_PROXY_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+/// Common bits for \a raw_ostream_proxy_adaptor<>, split out to dedup in
+/// template instantions.
+class raw_ostream_proxy_adaptor_base {
+protected:
+  raw_ostream_proxy_adaptor_base() = delete;
+  raw_ostream_proxy_adaptor_base(const raw_ostream_proxy_adaptor_base &) =
+      delete;
+
+  explicit raw_ostream_proxy_adaptor_base(raw_ostream &OS)
+      : OS(&OS), PreferredBufferSize(OS.GetBufferSize()) {
+    // Drop OS's buffer to make this->flush() forward. This proxy will add a
+    // buffer in its place.
+    OS.SetUnbuffered();
+  }
+
+  ~raw_ostream_proxy_adaptor_base() {
+    assert(!OS && "Derived objects should call resetProxiedOS()");
+  }
+
+  /// Stop proxying the stream, taking the derived object by reference as \p
+  /// ThisProxyOS.  Updates \p ThisProxyOS to stop buffering before setting \a
+  /// OS to \c nullptr, ensuring that future writes crash immediately.
+  void resetProxiedOS(raw_ostream &ThisProxyOS) {
+    ThisProxyOS.SetUnbuffered();
+    OS = nullptr;
+  }
+
+  bool hasProxiedOS() const { return OS; }
+  raw_ostream &getProxiedOS() const {
+    assert(OS && "raw_ostream_proxy_adaptor use after reset");
+    return *OS;
+  }
+  size_t getPreferredBufferSize() const { return PreferredBufferSize; }
+
+private:
+  raw_ostream *OS;
+
+  /// Caches the value of OS->GetBufferSize() at construction time.
+  size_t PreferredBufferSize;
+};
+
+/// Adaptor to create a stream class that proxies another \a raw_ostream.
----------------
cachemeifyoucan wrote:

The goal for this class is to bridge some current usages of raw_ostream output to use VirtualOutputBackend/VirtualOutputFile. It would make more sense if look at it together with the 2nd commit.

After virtualizing the output, we have `VirtualOutputFile` that represents the output from llvm tools and the file can be `keep()` or `discard()` with proper error handling, etc. `VirtualOutputFile` should be owning the underlying output stream, for example, `raw_fd_ostream`. On the other hand, there are certain function/tool want to own its output stream, and a proxy to the actual underlying output stream can be created from `VirtualOutputFile` and the proxy can be owned by other part of the code.

Of course, when the `VirtualOutputFile` going to close the owning stream, it will make sure all proxies will be close and further write to the proxy will cause crash. This actually caught some bugs in our tools.

https://github.com/llvm/llvm-project/pull/68447


More information about the cfe-commits mailing list