Added the ability to dump hex bytes easily into a raw_ostream.

Unit tests were added to verify this functionality keeps working correctly.

Example output for raw hex bytes:
llvm::ArrayRef<uint8_t> Bytes = ...;
llvm::outs() << format_hex_bytes(Bytes);
554889e5 4881ec70 04000048 8d051002
00004c8d 05fd0100 004c8b0d d0020000

Example output for raw hex bytes with offsets:
llvm::outs() << format_hex_bytes(Bytes, 0x100000d10);
0x0000000100000d10: 554889e5 4881ec70 04000048 8d051002
0x0000000100000d20: 00004c8d 05fd0100 004c8b0d d0020000

Example output for raw hex bytes with ASCII with offsets:
llvm::outs() << format_hex_bytes_with_ascii(Bytes, 0x100000d10);
0x0000000100000d10: 554889e5 4881ec70 04000048 8d051002 |UH.?H.?p...H....|
0x0000000100000d20: 00004c8d 05fd0100 004c8b0d d0020000 |..L..?...L..?...|

The default groups bytes into 4 byte groups, but this can be changed to 1 byte:
llvm::outs() << format_hex_bytes(Bytes, 0x100000d10, 16 /*NumPerLine*/, 1 /*ByteGroupSize*/);
0x0000000100000d10: 55 48 89 e5 48 81 ec 70 04 00 00 48 8d 05 10 02
0x0000000100000d20: 00 00 4c 8d 05 fd 01 00 00 4c 8b 0d d0 02 00 00

llvm::outs() << format_hex_bytes(Bytes, 0x100000d10, 16 /*NumPerLine*/, 2 /*ByteGroupSize*/);
0x0000000100000d10: 5548 89e5 4881 ec70 0400 0048 8d05 1002
0x0000000100000d20: 0000 4c8d 05fd 0100 004c 8b0d d002 0000

llvm::outs() << format_hex_bytes(Bytes, 0x100000d10, 8 /*NumPerLine*/, 1 /*ByteGroupSize*/);
0x0000000100000d10: 55 48 89 e5 48 81 ec 70
0x0000000100000d18: 04 00 00 48 8d 05 10 02
0x0000000100000d20: 00 00 4c 8d 05 fd 01 00
0x0000000100000d28: 00 4c 8b 0d d0 02 00 00

https://reviews.llvm.org/D26405

llvm-svn: 286316
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index b6835e3..42f121d 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -352,6 +352,61 @@
   return *this;
 }
 
+raw_ostream &raw_ostream::operator<<(const FormattedHexBytes &FB) {
+  size_t LineIndex = 0;
+  const size_t Size = FB.Bytes.size();
+  HexPrintStyle OffsetStyle =
+      FB.Upper ? HexPrintStyle::PrefixUpper : HexPrintStyle::PrefixLower;
+  HexPrintStyle ByteStyle =
+      FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower;
+  while (LineIndex < Size) {
+    if (FB.FirstByteOffset.hasValue()) {
+      uint64_t Offset = FB.FirstByteOffset.getValue();
+      llvm::write_hex(*this, Offset + LineIndex, OffsetStyle,
+                      sizeof(Offset) * 2 + 2);
+      *this << ": ";
+    }
+    // Print the hex bytes for this line
+    uint32_t I = 0;
+    for (I = 0; I < FB.NumPerLine; ++I) {
+      size_t Index = LineIndex + I;
+      if (Index >= Size)
+        break;
+      if (I && (I % FB.ByteGroupSize) == 0)
+        *this << " ";
+      llvm::write_hex(*this, FB.Bytes[Index], ByteStyle, 2);
+    }
+    uint32_t BytesDisplayed = I;
+    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.
+      for (; I < FB.NumPerLine; ++I) {
+        if (I && (I % FB.ByteGroupSize) == 0)
+          indent(3);
+        else
+          indent(2);
+      }
+      *this << "  |";
+      // Print the ASCII char values for each byte on this line
+      for (I = 0; I < FB.NumPerLine; ++I) {
+        size_t Index = LineIndex + I;
+        if (Index >= Size)
+          break;
+        char ch = (char)FB.Bytes[Index];
+        if (isprint(ch))
+          *this << ch;
+        else
+          *this << '.';
+      }
+      *this << '|';
+    }
+    LineIndex += BytesDisplayed;
+    if (LineIndex < Size)
+      *this << '\n';
+  }
+  return *this;
+}
+
 /// indent - Insert 'NumSpaces' spaces.
 raw_ostream &raw_ostream::indent(unsigned NumSpaces) {
   static const char Spaces[] = "                                "