Index: include/llvm/Support/ScopedPrinter.h =================================================================== --- include/llvm/Support/ScopedPrinter.h +++ include/llvm/Support/ScopedPrinter.h @@ -261,7 +261,11 @@ } void printString(StringRef Label, const std::string &Value) { - startLine() << Label << ": " << Value << "\n"; + printString(Label, StringRef(Value)); + } + + void printString(StringRef Label, const char* Value) { + printString(Label, StringRef(Value)); } template Index: tools/llvm-readobj/COFFDumper.cpp =================================================================== --- tools/llvm-readobj/COFFDumper.cpp +++ tools/llvm-readobj/COFFDumper.cpp @@ -1790,10 +1790,9 @@ if (Obj->isLittleEndian()) prettyPrintStackMap( - llvm::outs(), - StackMapV2Parser(StackMapContentsArray)); + W, StackMapV2Parser(StackMapContentsArray)); else - prettyPrintStackMap(llvm::outs(), + prettyPrintStackMap(W, StackMapV2Parser(StackMapContentsArray)); } Index: tools/llvm-readobj/COFFImportDumper.cpp =================================================================== --- tools/llvm-readobj/COFFImportDumper.cpp +++ tools/llvm-readobj/COFFImportDumper.cpp @@ -15,34 +15,44 @@ #include "llvm/BinaryFormat/COFF.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" +#include "llvm/Support/ScopedPrinter.h" using namespace llvm::object; namespace llvm { -void dumpCOFFImportFile(const COFFImportFile *File) { - outs() << '\n'; - outs() << "File: " << File->getFileName() << "\n"; - outs() << "Format: COFF-import-file\n"; +void dumpCOFFImportFile(const COFFImportFile *File, ScopedPrinter &Writer) { + Writer.startLine() << '\n'; + Writer.printString("File", File->getFileName()); + Writer.printString("Format", "COFF-import-file"); const coff_import_header *H = File->getCOFFImportHeader(); switch (H->getType()) { - case COFF::IMPORT_CODE: outs() << "Type: code\n"; break; - case COFF::IMPORT_DATA: outs() << "Type: data\n"; break; - case COFF::IMPORT_CONST: outs() << "Type: const\n"; break; + case COFF::IMPORT_CODE: Writer.printString("Type", "code"); break; + case COFF::IMPORT_DATA: Writer.printString("Type", "data"); break; + case COFF::IMPORT_CONST: Writer.printString("Type", "const"); break; } switch (H->getNameType()) { - case COFF::IMPORT_ORDINAL: outs() << "Name type: ordinal\n"; break; - case COFF::IMPORT_NAME: outs() << "Name type: name\n"; break; - case COFF::IMPORT_NAME_NOPREFIX: outs() << "Name type: noprefix\n"; break; - case COFF::IMPORT_NAME_UNDECORATE: outs() << "Name type: undecorate\n"; break; + case COFF::IMPORT_ORDINAL: + Writer.printString("Name type", "ordinal"); + break; + case COFF::IMPORT_NAME: + Writer.printString("Name type", "name"); + break; + case COFF::IMPORT_NAME_NOPREFIX: + Writer.printString("Name type", "noprefix"); + break; + case COFF::IMPORT_NAME_UNDECORATE: + Writer.printString("Name type", "undecorate"); + break; } for (const object::BasicSymbolRef &Sym : File->symbols()) { - outs() << "Symbol: "; - Sym.printName(outs()); - outs() << "\n"; + raw_ostream &OS = Writer.startLine(); + OS << "Symbol: "; + Sym.printName(OS); + OS << "\n"; } } Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -1830,9 +1830,8 @@ std::stable_sort(Libs.begin(), Libs.end()); - for (const auto &L : Libs) { - outs() << " " << L << "\n"; - } + for (const auto &L : Libs) + W.startLine() << L << "\n"; } @@ -1866,7 +1865,7 @@ } template void ELFDumper::printLoadName() { - outs() << "LoadName: " << SOName << '\n'; + W.startLine() << "LoadName: " << SOName << '\n'; } template @@ -2400,8 +2399,8 @@ ArrayRef StackMapContentsArray = unwrapOrError(Obj->getSectionContents(StackMapSection)); - prettyPrintStackMap(outs(), StackMapV2Parser( - StackMapContentsArray)); + prettyPrintStackMap( + W, StackMapV2Parser(StackMapContentsArray)); } template void ELFDumper::printGroupSections() { Index: tools/llvm-readobj/MachODumper.cpp =================================================================== --- tools/llvm-readobj/MachODumper.cpp +++ tools/llvm-readobj/MachODumper.cpp @@ -667,12 +667,11 @@ StackMapContents.size()); if (Obj->isLittleEndian()) - prettyPrintStackMap( - llvm::outs(), - StackMapV2Parser(StackMapContentsArray)); + prettyPrintStackMap( + W, StackMapV2Parser(StackMapContentsArray)); else - prettyPrintStackMap(llvm::outs(), - StackMapV2Parser(StackMapContentsArray)); + prettyPrintStackMap(W, + StackMapV2Parser(StackMapContentsArray)); } void MachODumper::printMachODataInCode() { Index: tools/llvm-readobj/ObjDumper.h =================================================================== --- tools/llvm-readobj/ObjDumper.h +++ tools/llvm-readobj/ObjDumper.h @@ -101,7 +101,8 @@ ScopedPrinter &Writer, std::unique_ptr &Result); -void dumpCOFFImportFile(const object::COFFImportFile *File); +void dumpCOFFImportFile(const object::COFFImportFile *File, + ScopedPrinter &Writer); void dumpCodeViewMergedTypes( ScopedPrinter &Writer, llvm::codeview::MergingTypeTableBuilder &IDTable, Index: tools/llvm-readobj/StackMapPrinter.h =================================================================== --- tools/llvm-readobj/StackMapPrinter.h +++ tools/llvm-readobj/StackMapPrinter.h @@ -11,69 +11,70 @@ #define LLVM_TOOLS_LLVM_READOBJ_STACKMAPPRINTER_H #include "llvm/Object/StackMapParser.h" +#include "llvm/Support/ScopedPrinter.h" namespace llvm { // Pretty print a stackmap to the given ostream. -template -void prettyPrintStackMap(OStreamT &OS, const StackMapParserT &SMP) { +template +void prettyPrintStackMap(ScopedPrinter &W, const StackMapParserT &SMP) { - OS << "LLVM StackMap Version: " << SMP.getVersion() - << "\nNum Functions: " << SMP.getNumFunctions(); + W.printNumber("LLVM StackMap Version", SMP.getVersion()); + W.printNumber("Num Functions", SMP.getNumFunctions()); // Functions: for (const auto &F : SMP.functions()) - OS << "\n Function address: " << F.getFunctionAddress() + W.startLine() << " Function address: " << F.getFunctionAddress() << ", stack size: " << F.getStackSize() - << ", callsite record count: " << F.getRecordCount(); + << ", callsite record count: " << F.getRecordCount() << "\n"; // Constants: - OS << "\nNum Constants: " << SMP.getNumConstants(); + W.printNumber("Num Constants", SMP.getNumConstants()); unsigned ConstantIndex = 0; for (const auto &C : SMP.constants()) - OS << "\n #" << ++ConstantIndex << ": " << C.getValue(); + W.startLine() << " #" << ++ConstantIndex << ": " << C.getValue() << "\n"; // Records: - OS << "\nNum Records: " << SMP.getNumRecords(); + W.printNumber("Num Records", SMP.getNumRecords()); for (const auto &R : SMP.records()) { - OS << "\n Record ID: " << R.getID() - << ", instruction offset: " << R.getInstructionOffset() - << "\n " << R.getNumLocations() << " locations:"; + W.startLine() << " Record ID: " << R.getID() + << ", instruction offset: " << R.getInstructionOffset() + << "\n"; + W.startLine() << " " << R.getNumLocations() << " locations:\n"; unsigned LocationIndex = 0; for (const auto &Loc : R.locations()) { - OS << "\n #" << ++LocationIndex << ": "; + raw_ostream &OS = W.startLine(); + OS << " #" << ++LocationIndex << ": "; switch (Loc.getKind()) { case StackMapParserT::LocationKind::Register: - OS << "Register R#" << Loc.getDwarfRegNum(); + OS << "Register R#" << Loc.getDwarfRegNum() << "\n"; break; case StackMapParserT::LocationKind::Direct: - OS << "Direct R#" << Loc.getDwarfRegNum() << " + " - << Loc.getOffset(); + OS << "Direct R#" << Loc.getDwarfRegNum() << " + " << Loc.getOffset() + << "\n"; break; case StackMapParserT::LocationKind::Indirect: - OS << "Indirect [R#" << Loc.getDwarfRegNum() << " + " - << Loc.getOffset() << "]"; + OS << "Indirect [R#" << Loc.getDwarfRegNum() << " + " << Loc.getOffset() + << "]\n"; break; case StackMapParserT::LocationKind::Constant: - OS << "Constant " << Loc.getSmallConstant(); + OS << "Constant " << Loc.getSmallConstant() << "\n"; break; case StackMapParserT::LocationKind::ConstantIndex: OS << "ConstantIndex #" << Loc.getConstantIndex() << " (" - << SMP.getConstant(Loc.getConstantIndex()).getValue() << ")"; + << SMP.getConstant(Loc.getConstantIndex()).getValue() << ")\n"; break; } } - OS << "\n " << R.getNumLiveOuts() << " live-outs: [ "; + raw_ostream &OS = W.startLine(); + OS << " " << R.getNumLiveOuts() << " live-outs: [ "; for (const auto &LO : R.liveouts()) OS << "R#" << LO.getDwarfRegNum() << " (" << LO.getSizeInBytes() << "-bytes) "; OS << "]\n"; } - - OS << "\n"; - } } Index: tools/llvm-readobj/llvm-readobj.cpp =================================================================== --- tools/llvm-readobj/llvm-readobj.cpp +++ tools/llvm-readobj/llvm-readobj.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" @@ -375,19 +376,19 @@ } /// @brief Dumps the specified object file. -static void dumpObject(const ObjectFile *Obj) { - ScopedPrinter Writer(outs()); +static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer) { std::unique_ptr Dumper; if (std::error_code EC = createDumper(Obj, Writer, Dumper)) reportError(Obj->getFileName(), EC); if (opts::Output == opts::LLVM) { - outs() << '\n'; - outs() << "File: " << Obj->getFileName() << "\n"; - outs() << "Format: " << Obj->getFileFormatName() << "\n"; - outs() << "Arch: " << Triple::getArchTypeName( - (llvm::Triple::ArchType)Obj->getArch()) << "\n"; - outs() << "AddressSize: " << (8 * Obj->getBytesInAddress()) << "bit\n"; + Writer.startLine() << "\n"; + Writer.printString("File", Obj->getFileName()); + Writer.printString("Format", Obj->getFileFormatName()); + Writer.printString("Arch", Triple::getArchTypeName( + (llvm::Triple::ArchType)Obj->getArch())); + Writer.printString("AddressSize", + formatv("{0}bit", 8 * Obj->getBytesInAddress())); Dumper->printLoadName(); } @@ -477,7 +478,7 @@ } /// @brief Dumps each object file in \a Arc; -static void dumpArchive(const Archive *Arc) { +static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) { Error Err = Error::success(); for (auto &Child : Arc->children(Err)) { Expected> ChildOrErr = Child.getAsBinary(); @@ -488,9 +489,9 @@ continue; } if (ObjectFile *Obj = dyn_cast(&*ChildOrErr.get())) - dumpObject(Obj); + dumpObject(Obj, Writer); else if (COFFImportFile *Imp = dyn_cast(&*ChildOrErr.get())) - dumpCOFFImportFile(Imp); + dumpCOFFImportFile(Imp, Writer); else reportError(Arc->getFileName(), readobj_error::unrecognized_file_format); } @@ -499,16 +500,17 @@ } /// @brief Dumps each object file in \a MachO Universal Binary; -static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary) { +static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary, + ScopedPrinter &Writer) { for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) { Expected> ObjOrErr = Obj.getAsObjectFile(); if (ObjOrErr) - dumpObject(&*ObjOrErr.get()); + dumpObject(&*ObjOrErr.get(), Writer); else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { reportError(UBinary->getFileName(), ObjOrErr.takeError()); } else if (Expected> AOrErr = Obj.getAsArchive()) - dumpArchive(&*AOrErr.get()); + dumpArchive(&*AOrErr.get(), Writer); } } @@ -523,6 +525,7 @@ /// @brief Opens \a File and dumps it. static void dumpInput(StringRef File) { + ScopedPrinter Writer(outs()); // Attempt to open the binary. Expected> BinaryOrErr = createBinary(File); @@ -531,14 +534,14 @@ Binary &Binary = *BinaryOrErr.get().getBinary(); if (Archive *Arc = dyn_cast(&Binary)) - dumpArchive(Arc); + dumpArchive(Arc, Writer); else if (MachOUniversalBinary *UBinary = dyn_cast(&Binary)) - dumpMachOUniversalBinary(UBinary); + dumpMachOUniversalBinary(UBinary, Writer); else if (ObjectFile *Obj = dyn_cast(&Binary)) - dumpObject(Obj); + dumpObject(Obj, Writer); else if (COFFImportFile *Import = dyn_cast(&Binary)) - dumpCOFFImportFile(Import); + dumpCOFFImportFile(Import, Writer); else if (WindowsResource *WinRes = dyn_cast(&Binary)) dumpWindowsResourceFile(WinRes); else