summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-08-17 01:35:29 +0000
committerChris Lattner <sabre@nondot.org>2008-08-17 01:35:29 +0000
commit60d396262460f0613175e52c00be5e8bfb89d8fb (patch)
treeb09a27364396b43a1bd0066f173f007dab70b7ca
parentafc20ae0e538a731f379dc1ae9ac564023078978 (diff)
downloadllvm-60d396262460f0613175e52c00be5e8bfb89d8fb.tar.gz
llvm-60d396262460f0613175e52c00be5e8bfb89d8fb.tar.bz2
llvm-60d396262460f0613175e52c00be5e8bfb89d8fb.tar.xz
add a new raw_ostream class which is an extremely high performance ostream that
can *only* output data (no seeking, reading, etc). This is adapted from the clang "-E outputter", and is roughly 10% faster than stdio on darwin and 30% (or more) faster than std::ostream. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54855 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Support/raw_ostream.h170
-rw-r--r--lib/Support/raw_ostream.cpp64
2 files changed, 234 insertions, 0 deletions
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
new file mode 100644
index 0000000000..2a4d74fc83
--- /dev/null
+++ b/include/llvm/Support/raw_ostream.h
@@ -0,0 +1,170 @@
+//===--- raw_ostream.h - Raw output stream ---------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the raw_ostream class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RAW_OSTREAM_H
+#define LLVM_SUPPORT_RAW_OSTREAM_H
+
+#include <string>
+
+namespace llvm {
+
+/// raw_ostream - This class implements an extremely fast bulk output stream
+/// that can *only* output to a stream. It does not support seeking, reopening,
+/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs
+/// a chunk at a time.
+class raw_ostream {
+protected:
+ char *OutBufStart, *OutBufEnd, *OutBufCur;
+public:
+ raw_ostream() {
+ // Start out ready to flush.
+ OutBufStart = OutBufEnd = OutBufCur = 0;
+ }
+ virtual ~raw_ostream() {}
+
+ //===--------------------------------------------------------------------===//
+ // Configuration Interface
+ //===--------------------------------------------------------------------===//
+
+ /// SetBufferSize - Set the internal buffer size to the specified amount
+ /// instead of the default.
+ void SetBufferSize(unsigned Size) {
+ assert(Size >= 64 &&
+ "Buffer size must be somewhat large for invariants to hold");
+ flush();
+
+ delete [] OutBufStart;
+ OutBufStart = new char[Size];
+ OutBufEnd = OutBufStart+Size;
+ OutBufCur = OutBufStart;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Data Output Interface
+ //===--------------------------------------------------------------------===//
+
+ void flush() {
+ if (OutBufCur != OutBufStart)
+ flush_impl();
+ }
+
+ raw_ostream &operator<<(char C) {
+ if (OutBufCur >= OutBufEnd)
+ flush_impl();
+ *OutBufCur++ = C;
+ return *this;
+ }
+
+ raw_ostream &operator<<(const char *Str) {
+ return OutputData(Str, strlen(Str));
+ }
+
+ raw_ostream &OutputData(const char *Ptr, unsigned Size) {
+ if (OutBufCur+Size > OutBufEnd)
+ flush_impl();
+
+ // Handle short strings specially, memcpy isn't very good at very short
+ // strings.
+ switch (Size) {
+// case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
+ case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
+ case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
+ case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
+ case 0: break;
+ default:
+ // Normally the string to emit is shorter than the buffer.
+ if (Size <= unsigned(OutBufEnd-OutBufStart)) {
+ memcpy(OutBufCur, Ptr, Size);
+ break;
+ }
+
+ // If emitting a string larger than our buffer, emit in chunks. In this
+ // case we know that we just flushed the buffer.
+ while (Size) {
+ unsigned NumToEmit = OutBufEnd-OutBufStart;
+ if (Size < NumToEmit) NumToEmit = Size;
+ assert(OutBufCur == OutBufStart);
+ memcpy(OutBufStart, Ptr, NumToEmit);
+ Ptr += NumToEmit;
+ OutBufCur = OutBufStart + NumToEmit;
+ flush_impl();
+ }
+ break;
+ }
+ OutBufCur += Size;
+ return *this;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Subclass Interface
+ //===--------------------------------------------------------------------===//
+
+protected:
+
+ /// flush_impl - The is the piece of the class that is implemented by
+ /// subclasses. This outputs the currently buffered data and resets the
+ /// buffer to empty.
+ virtual void flush_impl() = 0;
+
+ /// HandleFlush - A stream's implementation of flush should call this after
+ /// emitting the bytes to the data sink.
+ void HandleFlush() {
+ if (OutBufStart == 0)
+ SetBufferSize(4096);
+ OutBufCur = OutBufStart;
+ }
+private:
+ // An out of line virtual method to provide a home for the class vtable.
+ virtual void handle();
+};
+
+/// raw_fd_ostream - A raw_ostream that writes to a file descriptor.
+///
+class raw_fd_ostream : public raw_ostream {
+ int FD;
+ bool ShouldClose;
+public:
+ /// raw_fd_ostream - Open the specified file for writing. If an error occurs,
+ /// information about the error is put into ErrorInfo, and the stream should
+ /// be immediately destroyed.
+ raw_fd_ostream(const char *Filename, std::string &ErrorInfo);
+
+ /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If
+ /// ShouldClose is true, this closes the file when
+ raw_fd_ostream(int fd, bool shouldClose) : FD(fd), ShouldClose(shouldClose) {}
+
+ ~raw_fd_ostream();
+
+ /// flush_impl - The is the piece of the class that is implemented by
+ /// subclasses. This outputs the currently buffered data and resets the
+ /// buffer to empty.
+ virtual void flush_impl();
+};
+
+class raw_stdout_ostream : public raw_fd_ostream {
+ // An out of line virtual method to provide a home for the class vtable.
+ virtual void handle();
+public:
+ raw_stdout_ostream();
+};
+
+class raw_stderr_ostream : public raw_fd_ostream {
+ // An out of line virtual method to provide a home for the class vtable.
+ virtual void handle();
+public:
+ raw_stderr_ostream();
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
new file mode 100644
index 0000000000..ec7ac6d007
--- /dev/null
+++ b/lib/Support/raw_ostream.cpp
@@ -0,0 +1,64 @@
+//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This implements support for bulk buffered stream output.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#if !defined(_MSC_VER)
+#include <fcntl.h>
+#else
+#include <io.h>
+#define open(x,y,z) _open(x,y)
+#define write(fd, start, size) _write(fd, start, size)
+#define close(fd) _close(fd)
+#endif
+
+// An out of line virtual method to provide a home for the class vtable.
+void raw_ostream::handle() {}
+
+//===----------------------------------------------------------------------===//
+// raw_fd_ostream
+//===----------------------------------------------------------------------===//
+
+/// raw_fd_ostream - Open the specified file for writing. If an error occurs,
+/// information about the error is put into ErrorInfo, and the stream should
+/// be immediately destroyed.
+raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo) {
+ FD = open(Filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (FD < 0) {
+ ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
+ ShouldClose = false;
+ } else {
+ ShouldClose = true;
+ }
+}
+
+raw_fd_ostream::~raw_fd_ostream() {
+ flush();
+ if (ShouldClose)
+ close(FD);
+}
+
+void raw_fd_ostream::flush_impl() {
+ if (OutBufCur-OutBufStart)
+ write(FD, OutBufStart, OutBufCur-OutBufStart);
+ HandleFlush();
+}
+
+
+raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
+raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false) {}
+
+// An out of line virtual method to provide a home for the class vtable.
+void raw_stdout_ostream::handle() {}
+void raw_stderr_ostream::handle() {}