Index: include/llvm/Support/Format.h =================================================================== --- include/llvm/Support/Format.h +++ include/llvm/Support/Format.h @@ -225,6 +228,60 @@ Val5, Val6); } +class FormattedString { + StringRef Str; + unsigned Width; + bool Left; + friend class raw_ostream; +public: + FormattedString(StringRef S, unsigned W, bool L) + : Str(S), Width(W), Left(L) { } +}; + +/// rightJustify - write pad spaces to left of string so total output is +/// \p Width characters. If \p Str is larger that \p Width, full string +/// is writing with no padding. +inline FormattedString leftJustify(StringRef Str, unsigned Width) { + return FormattedString(Str, Width, true); +} + +/// leftJustify - append pad spaces after string so total output is +/// \p Width characters. If \p Str is larger that \p Width, full string +/// is writing with no padding. +inline FormattedString rightJustify(StringRef Str, unsigned Width) { + return FormattedString(Str, Width, false); +} + +class FormattedNumber { + uint64_t Value; + unsigned Width; + bool Hex; + bool Upper; + bool Negate; + friend class raw_ostream; +public: + FormattedNumber(unsigned long long N, unsigned W, bool H, bool U, bool Neg) + : Value(N), Width(W), Hex(H), Upper(U), Negate(Neg) { } +}; + +/// formatHex - Output \p N as a fixed width hexadecimal. Examples: +/// formatHex(255, 2) => 0xff +/// formatHex(255, 2, true) => 0xFF +/// formatHex(255, 4) => 0x00ff +inline FormattedNumber formatHex(uint64_t N, unsigned Width, bool Upper=false) { + assert(Width <= 16 && "hex width must be <= 16"); + return FormattedNumber(N, Width, true, Upper, false); +} + +/// formatDecimal - Output \p N as a fixed width decimal. Examples: +/// formatDecimal(0, 5) => " 0" +/// formatDecimal(255, 5) => " 255" +/// formatDecimal(-1, 3) => " -1" +inline FormattedNumber formatDecimal(int64_t N, unsigned Width) { + return FormattedNumber(N, Width, false, false, N < 0); +} + + } // end namespace llvm #endif Index: include/llvm/Support/raw_ostream.h =================================================================== --- include/llvm/Support/raw_ostream.h +++ include/llvm/Support/raw_ostream.h @@ -21,6 +21,8 @@ namespace llvm { class format_object_base; + class FormattedString; + class FormattedNumber; template class SmallVectorImpl; @@ -211,10 +213,15 @@ // Formatted output, see the format() function in Support/Format.h. raw_ostream &operator<<(const format_object_base &Fmt); + // Formatted output, see the leftJustify() function in Support/Format.h. + raw_ostream &operator<<(const FormattedString &); + + // Formatted output, see the formatHex() function in Support/Format.h. + raw_ostream &operator<<(const FormattedNumber &); + /// indent - Insert 'NumSpaces' spaces. raw_ostream &indent(unsigned NumSpaces); - /// Changes the foreground color of text that will be output from this point /// forward. /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to Index: lib/Support/raw_ostream.cpp =================================================================== --- lib/Support/raw_ostream.cpp +++ lib/Support/raw_ostream.cpp @@ -20,6 +20,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include @@ -394,6 +429,62 @@ } } +raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { + unsigned Len = FS.Str.size(); + int PadAmount = FS.Width - Len; + if (!FS.Left && (PadAmount > 0)) + this->indent(PadAmount); + this->operator<<(FS.Str); + if (FS.Left && (PadAmount > 0)) + this->indent(PadAmount); + return *this; +} + +raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { + if (FN.Hex) { + unsigned Nibbles = (64 - countLeadingZeros(FN.Value)+3)/4; + if (FN.Width > Nibbles) + Nibbles = FN.Width; + + char NumberBuffer[20] = "0x0000000000000000"; + char *EndPtr = NumberBuffer+2+Nibbles; + char *CurPtr = EndPtr; + const char A = FN.Upper ? 'A' : 'a'; + unsigned long long N = FN.Value; + while (N) { + uintptr_t x = N % 16; + *--CurPtr = (x < 10 ? '0' + x : A + x - 10); + N /= 16; + } + + return write(NumberBuffer, Nibbles); + } else { + // Zero is a special case. + if (FN.Value == 0) { + this->indent(FN.Width-1); + return *this << '0'; + } + char NumberBuffer[32]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + int64_t N = FN.Value; + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + int Len = EndPtr - CurPtr; + int Pad = FN.Width - Len; + if (FN.Negate) { + *this << '-'; + --Pad; + } + if (Pad > 0) + this->indent(Pad); + return write(CurPtr, Len); + } +} + + /// indent - Insert 'NumSpaces' spaces. raw_ostream &raw_ostream::indent(unsigned NumSpaces) { static const char Spaces[] = " " Index: tools/llvm-objdump/MachODump.cpp =================================================================== --- tools/llvm-objdump/MachODump.cpp +++ tools/llvm-objdump/MachODump.cpp @@ -2476,18 +2476,17 @@ // Table lines look like: // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard - outs() << format("%-8s %-18s 0x%08" PRIX64 " %-8s %-8" PRId64 " %-20s", - SegmentName.str().c_str(), - SectionName.str().c_str(), - Address, - Entry.typeName().str().c_str(), - Entry.addend(), - ordinalName(Obj, Entry.ordinal()).str().c_str()) - << Entry.symbolName(); + StringRef Attr; if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) - outs() << " (weak_import)\n"; - else - outs() << "\n"; + Attr = " (weak_import)"; + outs() << leftJustify(SegmentName, 8) << " " + << leftJustify(SectionName, 18) << " " + << formatHex(Address, 9, true) << " " + << leftJustify(Entry.typeName(), 8) << " " + << formatDecimal(Entry.addend(), 8) << " " + << leftJustify(ordinalName(Obj, Entry.ordinal()), 16) << " " + << Entry.symbolName() + << Attr << "\n"; } } @@ -2510,11 +2509,10 @@ // Table lines look like: // __DATA __got 0x00012010 libSystem ___stack_chk_guard - outs() << format("%-8s %-18s 0x%08" PRIX64 " %-20s", - SegmentName.str().c_str(), - SectionName.str().c_str(), - Address, - ordinalName(Obj, Entry.ordinal()).str().c_str()) + outs() << leftJustify(SegmentName, 8) << " " + << leftJustify(SectionName, 18) << " " + << formatHex(Address, 9, true) << " " + << leftJustify(ordinalName(Obj, Entry.ordinal()), 16) << " " << Entry.symbolName() << "\n"; } } @@ -2545,12 +2543,11 @@ // Table lines look like: // __DATA __data 0x00001000 pointer 0 _foo - outs() << format("%-8s %-18s 0x%08" PRIX64 " %-8s %-8" PRId64 " ", - SegmentName.str().c_str(), - SectionName.str().c_str(), - Address, - Entry.typeName().str().c_str(), - Entry.addend()) + outs() << leftJustify(SegmentName, 8) << " " + << leftJustify(SectionName, 18) << " " + << formatHex(Address, 9, true) << " " + << leftJustify(Entry.typeName(), 8) << " " + << formatDecimal(Entry.addend(), 8) << " " << Entry.symbolName() << "\n"; } }