aboutsummaryrefslogtreecommitdiff
path: root/lib/Support/raw_ostream.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
commitb915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch)
tree98b8f811c7aff2547cab8642daf372d6c59502fb /lib/Support/raw_ostream.cpp
parent6421cca32f69ac849537a3cff78c352195e99f1b (diff)
downloadsrc-b915e9e0fc85ba6f398b3fab0db6a81a8913af94.tar.gz
src-b915e9e0fc85ba6f398b3fab0db6a81a8913af94.zip
Vendor import of llvm trunk r290819:vendor/llvm/llvm-trunk-r290819
Notes
Notes: svn path=/vendor/llvm/dist/; revision=311116 svn path=/vendor/llvm/llvm-trunk-r290819/; revision=311117; tag=vendor/llvm/llvm-trunk-r290819
Diffstat (limited to 'lib/Support/raw_ostream.cpp')
-rw-r--r--lib/Support/raw_ostream.cpp266
1 files changed, 122 insertions, 144 deletions
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index 275fe1d49459..d073802db932 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -20,11 +20,16 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/NativeFormatting.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
+#include <algorithm>
#include <cctype>
#include <cerrno>
+#include <cstdio>
+#include <iterator>
#include <sys/stat.h>
#include <system_error>
@@ -110,73 +115,28 @@ void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
}
raw_ostream &raw_ostream::operator<<(unsigned long N) {
- // Zero is a special case.
- if (N == 0)
- return *this << '0';
-
- char NumberBuffer[20];
- char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
- char *CurPtr = EndPtr;
-
- while (N) {
- *--CurPtr = '0' + char(N % 10);
- N /= 10;
- }
- return write(CurPtr, EndPtr-CurPtr);
+ write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer);
+ return *this;
}
raw_ostream &raw_ostream::operator<<(long N) {
- if (N < 0) {
- *this << '-';
- // Avoid undefined behavior on LONG_MIN with a cast.
- N = -(unsigned long)N;
- }
-
- return this->operator<<(static_cast<unsigned long>(N));
+ write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer);
+ return *this;
}
raw_ostream &raw_ostream::operator<<(unsigned long long N) {
- // Output using 32-bit div/mod when possible.
- if (N == static_cast<unsigned long>(N))
- return this->operator<<(static_cast<unsigned long>(N));
-
- char NumberBuffer[20];
- char *EndPtr = std::end(NumberBuffer);
- char *CurPtr = EndPtr;
-
- while (N) {
- *--CurPtr = '0' + char(N % 10);
- N /= 10;
- }
- return write(CurPtr, EndPtr-CurPtr);
+ write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer);
+ return *this;
}
raw_ostream &raw_ostream::operator<<(long long N) {
- if (N < 0) {
- *this << '-';
- // Avoid undefined behavior on INT64_MIN with a cast.
- N = -(unsigned long long)N;
- }
-
- return this->operator<<(static_cast<unsigned long long>(N));
+ write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer);
+ return *this;
}
raw_ostream &raw_ostream::write_hex(unsigned long long N) {
- // Zero is a special case.
- if (N == 0)
- return *this << '0';
-
- char NumberBuffer[16];
- char *EndPtr = std::end(NumberBuffer);
- char *CurPtr = EndPtr;
-
- while (N) {
- unsigned char x = static_cast<unsigned char>(N) % 16;
- *--CurPtr = hexdigit(x, /*LowerCase*/true);
- N /= 16;
- }
-
- return write(CurPtr, EndPtr-CurPtr);
+ llvm::write_hex(*this, N, HexPrintStyle::Lower);
+ return *this;
}
raw_ostream &raw_ostream::write_escaped(StringRef Str,
@@ -220,54 +180,15 @@ raw_ostream &raw_ostream::write_escaped(StringRef Str,
}
raw_ostream &raw_ostream::operator<<(const void *P) {
- *this << '0' << 'x';
-
- return write_hex((uintptr_t) P);
+ llvm::write_hex(*this, (uintptr_t)P, HexPrintStyle::PrefixLower);
+ return *this;
}
raw_ostream &raw_ostream::operator<<(double N) {
-#ifdef _WIN32
- // On MSVCRT and compatible, output of %e is incompatible to Posix
- // by default. Number of exponent digits should be at least 2. "%+03d"
- // FIXME: Implement our formatter to here or Support/Format.h!
-#if defined(__MINGW32__)
- // FIXME: It should be generic to C++11.
- if (N == 0.0 && std::signbit(N))
- return *this << "-0.000000e+00";
-#else
- int fpcl = _fpclass(N);
-
- // negative zero
- if (fpcl == _FPCLASS_NZ)
- return *this << "-0.000000e+00";
-#endif
-
- char buf[16];
- unsigned len;
- len = format("%e", N).snprint(buf, sizeof(buf));
- if (len <= sizeof(buf) - 2) {
- if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') {
- int cs = buf[len - 4];
- if (cs == '+' || cs == '-') {
- int c1 = buf[len - 2];
- int c0 = buf[len - 1];
- if (isdigit(static_cast<unsigned char>(c1)) &&
- isdigit(static_cast<unsigned char>(c0))) {
- // Trim leading '0': "...e+012" -> "...e+12\0"
- buf[len - 3] = c1;
- buf[len - 2] = c0;
- buf[--len] = 0;
- }
- }
- }
- return this->operator<<(buf);
- }
-#endif
- return this->operator<<(format("%e", N));
+ llvm::write_double(*this, N, FloatStyle::Exponent);
+ return *this;
}
-
-
void raw_ostream::flush_nonempty() {
assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
size_t Length = OutBufCur - OutBufStart;
@@ -344,10 +265,10 @@ void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) {
// 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 4: OutBufCur[3] = Ptr[3]; LLVM_FALLTHROUGH;
+ case 3: OutBufCur[2] = Ptr[2]; LLVM_FALLTHROUGH;
+ case 2: OutBufCur[1] = Ptr[1]; LLVM_FALLTHROUGH;
+ case 1: OutBufCur[0] = Ptr[0]; LLVM_FALLTHROUGH;
case 0: break;
default:
memcpy(OutBufCur, Ptr, Size);
@@ -382,7 +303,7 @@ raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
// space. Iterate until we win.
SmallVector<char, 128> V;
- while (1) {
+ while (true) {
V.resize(NextBufferSize);
// Try formatting into the SmallVector.
@@ -398,6 +319,12 @@ raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
}
}
+raw_ostream &raw_ostream::operator<<(const formatv_object_base &Obj) {
+ SmallString<128> S;
+ Obj.format(*this);
+ return *this;
+}
+
raw_ostream &raw_ostream::operator<<(const FormattedString &FS) {
unsigned Len = FS.Str.size();
int PadAmount = FS.Width - Len;
@@ -411,51 +338,99 @@ raw_ostream &raw_ostream::operator<<(const FormattedString &FS) {
raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) {
if (FN.Hex) {
- unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4;
- unsigned PrefixChars = FN.HexPrefix ? 2 : 0;
- unsigned Width = std::max(FN.Width, Nibbles + PrefixChars);
-
- char NumberBuffer[20] = "0x0000000000000000";
- if (!FN.HexPrefix)
- NumberBuffer[1] = '0';
- char *EndPtr = NumberBuffer+Width;
- char *CurPtr = EndPtr;
- unsigned long long N = FN.HexValue;
- while (N) {
- unsigned char x = static_cast<unsigned char>(N) % 16;
- *--CurPtr = hexdigit(x, !FN.Upper);
- N /= 16;
+ HexPrintStyle Style;
+ if (FN.Upper && FN.HexPrefix)
+ Style = HexPrintStyle::PrefixUpper;
+ else if (FN.Upper && !FN.HexPrefix)
+ Style = HexPrintStyle::Upper;
+ else if (!FN.Upper && FN.HexPrefix)
+ Style = HexPrintStyle::PrefixLower;
+ else
+ Style = HexPrintStyle::Lower;
+ llvm::write_hex(*this, FN.HexValue, Style, FN.Width);
+ } else {
+ llvm::SmallString<16> Buffer;
+ llvm::raw_svector_ostream Stream(Buffer);
+ llvm::write_integer(Stream, FN.DecValue, 0, IntegerStyle::Integer);
+ if (Buffer.size() < FN.Width)
+ indent(FN.Width - Buffer.size());
+ (*this) << Buffer;
+ }
+ return *this;
+}
+
+raw_ostream &raw_ostream::operator<<(const FormattedBytes &FB) {
+ if (FB.Bytes.empty())
+ return *this;
+
+ size_t LineIndex = 0;
+ auto Bytes = FB.Bytes;
+ const size_t Size = Bytes.size();
+ HexPrintStyle HPS = FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower;
+ uint64_t OffsetWidth = 0;
+ if (FB.FirstByteOffset.hasValue()) {
+ // Figure out how many nibbles are needed to print the largest offset
+ // represented by this data set, so that we can align the offset field
+ // to the right width.
+ size_t Lines = Size / FB.NumPerLine;
+ uint64_t MaxOffset = *FB.FirstByteOffset + Lines * FB.NumPerLine;
+ unsigned Power = 0;
+ if (MaxOffset > 0)
+ Power = llvm::Log2_64_Ceil(MaxOffset);
+ OffsetWidth = std::max<uint64_t>(4, llvm::alignTo(Power, 4) / 4);
+ }
+
+ // The width of a block of data including all spaces for group separators.
+ unsigned NumByteGroups =
+ alignTo(FB.NumPerLine, FB.ByteGroupSize) / FB.ByteGroupSize;
+ unsigned BlockCharWidth = FB.NumPerLine * 2 + NumByteGroups - 1;
+
+ while (!Bytes.empty()) {
+ indent(FB.IndentLevel);
+
+ if (FB.FirstByteOffset.hasValue()) {
+ uint64_t Offset = FB.FirstByteOffset.getValue();
+ llvm::write_hex(*this, Offset + LineIndex, HPS, OffsetWidth);
+ *this << ": ";
}
- return write(NumberBuffer, Width);
- } else {
- // Zero is a special case.
- if (FN.DecValue == 0) {
- this->indent(FN.Width-1);
- return *this << '0';
+ auto Line = Bytes.take_front(FB.NumPerLine);
+
+ size_t CharsPrinted = 0;
+ // Print the hex bytes for this line in groups
+ for (size_t I = 0; I < Line.size(); ++I, CharsPrinted += 2) {
+ if (I && (I % FB.ByteGroupSize) == 0) {
+ ++CharsPrinted;
+ *this << " ";
+ }
+ llvm::write_hex(*this, Line[I], HPS, 2);
}
- char NumberBuffer[32];
- char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
- char *CurPtr = EndPtr;
- bool Neg = (FN.DecValue < 0);
- uint64_t N = Neg ? -static_cast<uint64_t>(FN.DecValue) : FN.DecValue;
- while (N) {
- *--CurPtr = '0' + char(N % 10);
- N /= 10;
+
+ if (FB.ASCII) {
+ // Print any spaces needed for any bytes that we didn't print on this
+ // line so that the ASCII bytes are correctly aligned.
+ assert(BlockCharWidth >= CharsPrinted);
+ indent(BlockCharWidth - CharsPrinted + 2);
+ *this << "|";
+
+ // Print the ASCII char values for each byte on this line
+ for (uint8_t Byte : Line) {
+ if (isprint(Byte))
+ *this << static_cast<char>(Byte);
+ else
+ *this << '.';
+ }
+ *this << '|';
}
- int Len = EndPtr - CurPtr;
- int Pad = FN.Width - Len;
- if (Neg)
- --Pad;
- if (Pad > 0)
- this->indent(Pad);
- if (Neg)
- *this << '-';
- return write(CurPtr, Len);
+
+ Bytes = Bytes.drop_front(Line.size());
+ LineIndex += Line.size();
+ if (LineIndex < Size)
+ *this << '\n';
}
+ return *this;
}
-
/// indent - Insert 'NumSpaces' spaces.
raw_ostream &raw_ostream::indent(unsigned NumSpaces) {
static const char Spaces[] = " "
@@ -475,7 +450,6 @@ raw_ostream &raw_ostream::indent(unsigned NumSpaces) {
return *this;
}
-
//===----------------------------------------------------------------------===//
// Formatted Output
//===----------------------------------------------------------------------===//
@@ -563,7 +537,6 @@ raw_fd_ostream::~raw_fd_ostream() {
report_fatal_error("IO failure on output stream.", /*GenCrashDiag=*/false);
}
-
void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
assert(FD >= 0 && "File already closed.");
pos += Size;
@@ -625,7 +598,13 @@ void raw_fd_ostream::close() {
uint64_t raw_fd_ostream::seek(uint64_t off) {
assert(SupportsSeeking && "Stream does not support seeking!");
flush();
+#ifdef LLVM_ON_WIN32
+ pos = ::_lseeki64(FD, off, SEEK_SET);
+#elif defined(HAVE_LSEEK64)
+ pos = ::lseek64(FD, off, SEEK_SET);
+#else
pos = ::lseek(FD, off, SEEK_SET);
+#endif
if (pos == (uint64_t)-1)
error_detected();
return pos;
@@ -740,7 +719,6 @@ raw_ostream &llvm::nulls() {
return S;
}
-
//===----------------------------------------------------------------------===//
// raw_string_ostream
//===----------------------------------------------------------------------===//