diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index df7610b1d04..91287d0fe70 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -746,7 +746,8 @@ MCStreamer *createNullStreamer(MCContext &Ctx); /// /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. -MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, +MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 96e4bfeb0b7..ad1a2610281 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -25,27 +25,11 @@ namespace llvm { /// boundaries and querying the number of lines written to the stream. /// class formatted_raw_ostream : public raw_ostream { -public: - /// DELETE_STREAM - Tell the destructor to delete the held stream. - /// - static const bool DELETE_STREAM = true; - - /// PRESERVE_STREAM - Tell the destructor to not delete the held - /// stream. - /// - static const bool PRESERVE_STREAM = false; - -private: /// TheStream - The real stream we output to. We set it to be /// unbuffered, since we're already doing our own buffering. /// raw_ostream *TheStream; - /// DeleteStream - Do we need to delete TheStream in the - /// destructor? - /// - bool DeleteStream; - /// Position - The current output column and line of the data that's /// been flushed and the portion of the buffer that's been /// scanned. The line and column scheme is zero-based. @@ -73,36 +57,10 @@ private: /// void ComputePosition(const char *Ptr, size_t size); -public: - /// formatted_raw_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; the string will be empty if no error occurred. - /// - /// As a side effect, the given Stream is set to be Unbuffered. - /// This is because formatted_raw_ostream does its own buffering, - /// so it doesn't want another layer of buffering to be happening - /// underneath it. - /// - formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) - : TheStream(nullptr), DeleteStream(false), Position(0, 0) { - setStream(Stream, Delete); - } - explicit formatted_raw_ostream() - : TheStream(nullptr), DeleteStream(false), Position(0, 0) { - Scanned = nullptr; - } - - ~formatted_raw_ostream() { - flush(); - releaseStream(); - } - - void setStream(raw_ostream &Stream, bool Delete = false) { + void setStream(raw_ostream &Stream) { releaseStream(); TheStream = &Stream; - DeleteStream = Delete; // This formatted_raw_ostream inherits from raw_ostream, so it'll do its // own buffering, and it doesn't need or want TheStream to do another @@ -117,6 +75,30 @@ public: Scanned = nullptr; } +public: + /// formatted_raw_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; the string will be empty if no error occurred. + /// + /// As a side effect, the given Stream is set to be Unbuffered. + /// This is because formatted_raw_ostream does its own buffering, + /// so it doesn't want another layer of buffering to be happening + /// underneath it. + /// + formatted_raw_ostream(raw_ostream &Stream) + : TheStream(nullptr), Position(0, 0) { + setStream(Stream); + } + explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) { + Scanned = nullptr; + } + + ~formatted_raw_ostream() { + flush(); + releaseStream(); + } + /// PadToColumn - Align the output to some column number. If the current /// column is already equal to or more than NewCol, PadToColumn inserts one /// space. @@ -151,13 +133,11 @@ public: private: void releaseStream() { - // Delete the stream if needed. Otherwise, transfer the buffer - // settings from this raw_ostream back to the underlying stream. + // Transfer the buffer settings from this raw_ostream back to the underlying + // stream. if (!TheStream) return; - if (DeleteStream) - delete TheStream; - else if (size_t BufferSize = GetBufferSize()) + if (size_t BufferSize = GetBufferSize()) TheStream->SetBufferSize(BufferSize); else TheStream->SetUnbuffered(); diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index b1b56d6e122..12e35ec1015 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -22,6 +22,7 @@ #include "llvm-c/Disassembler.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Support/FormattedStream.h" #include #include #include @@ -52,7 +53,8 @@ namespace llvm { class formatted_raw_ostream; MCStreamer *createNullStreamer(MCContext &Ctx); - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); @@ -469,14 +471,16 @@ namespace llvm { return S; } - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr OS, bool IsVerboseAsm, bool UseDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) const { - MCStreamer *S = - llvm::createAsmStreamer(Ctx, OS, IsVerboseAsm, UseDwarfDirectory, - InstPrint, CE, TAB, ShowInst); - createAsmTargetStreamer(*S, OS, InstPrint, IsVerboseAsm); + formatted_raw_ostream &OSRef = *OS; + MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IsVerboseAsm, + UseDwarfDirectory, InstPrint, CE, + TAB, ShowInst); + createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm); return S; } diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 1b26ccef2b6..58532180e48 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -207,8 +207,7 @@ public: /// emitted. Typically this will involve several steps of code generation. /// This method should return true if emission of this file type is not /// supported, or false on success. - virtual bool addPassesToEmitFile(PassManagerBase &, - formatted_raw_ostream &, + virtual bool addPassesToEmitFile(PassManagerBase &, raw_ostream &, CodeGenFileType, bool /*DisableVerify*/ = true, AnalysisID /*StartAfter*/ = nullptr, @@ -257,7 +256,7 @@ public: /// Add passes to the specified pass manager to get the specified file /// emitted. Typically this will involve several steps of code generation. - bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, + bool addPassesToEmitFile(PassManagerBase &PM, raw_ostream &Out, CodeGenFileType FileType, bool DisableVerify = true, AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr) override; diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 30148446195..5e6bfb74537 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -140,12 +140,9 @@ static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM, return &MMI->getContext(); } -bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, - formatted_raw_ostream &Out, - CodeGenFileType FileType, - bool DisableVerify, - AnalysisID StartAfter, - AnalysisID StopAfter) { +bool LLVMTargetMachine::addPassesToEmitFile( + PassManagerBase &PM, raw_ostream &Out, CodeGenFileType FileType, + bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) { // Add common CodeGen passes. MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, StartAfter, StopAfter); @@ -184,8 +181,9 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, MCAsmBackend *MAB = getTarget().createMCAsmBackend(MRI, getTargetTriple(), TargetCPU); + auto FOut = llvm::make_unique(Out); MCStreamer *S = getTarget().createAsmStreamer( - *Context, Out, Options.MCOptions.AsmVerbose, + *Context, std::move(FOut), Options.MCOptions.AsmVerbose, Options.MCOptions.MCUseDwarfDirectory, InstPrinter, MCE, MAB, Options.MCOptions.ShowMCInst); AsmStreamer.reset(S); diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index ad73ddc5d7a..2bcdc27e965 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -38,7 +38,6 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" @@ -574,13 +573,11 @@ bool LTOCodeGenerator::compileOptimized(raw_ostream &out, std::string &errMsg) { legacy::PassManager codeGenPasses; - formatted_raw_ostream Out(out); - // If the bitcode files contain ARC code and were compiled with optimization, // the ObjCARCContractPass must be run, so do it unconditionally here. codeGenPasses.add(createObjCARCContractPass()); - if (TargetMach->addPassesToEmitFile(codeGenPasses, Out, + if (TargetMach->addPassesToEmitFile(codeGenPasses, out, TargetMachine::CGFT_ObjectFile)) { errMsg = "target file type not supported"; return false; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index ab6ae2586ea..144d35553b8 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -37,6 +37,7 @@ using namespace llvm; namespace { class MCAsmStreamer final : public MCStreamer { + std::unique_ptr OSOwner; formatted_raw_ostream &OS; const MCAsmInfo *MAI; std::unique_ptr InstPrinter; @@ -55,14 +56,15 @@ class MCAsmStreamer final : public MCStreamer { void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; public: - MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, + MCAsmStreamer(MCContext &Context, std::unique_ptr os, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *printer, MCCodeEmitter *emitter, MCAsmBackend *asmbackend, bool showInst) - : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), - InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend), - CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), - ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) { + : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner), + MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), + AsmBackend(asmbackend), CommentStream(CommentToEmit), + IsVerboseAsm(isVerboseAsm), ShowInst(showInst), + UseDwarfDirectory(useDwarfDirectory) { if (InstPrinter && IsVerboseAsm) InstPrinter->setCommentStream(CommentStream); } @@ -1312,10 +1314,10 @@ void MCAsmStreamer::FinishImpl() { } MCStreamer *llvm::createAsmStreamer(MCContext &Context, - formatted_raw_ostream &OS, + std::unique_ptr OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *IP, MCCodeEmitter *CE, MCAsmBackend *MAB, bool ShowInst) { - return new MCAsmStreamer(Context, OS, isVerboseAsm, useDwarfDirectory, IP, CE, - MAB, ShowInst); + return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, + useDwarfDirectory, IP, CE, MAB, ShowInst); } diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index d0e2010abfd..8a9437b75ff 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -15,6 +15,7 @@ #include "CPPTargetMachine.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Config/config.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" @@ -91,6 +92,7 @@ namespace { /// CppWriter - This class is the main chunk of code that converts an LLVM /// module to a C++ translation unit. class CppWriter : public ModulePass { + std::unique_ptr OutOwner; formatted_raw_ostream &Out; const Module *TheModule; uint64_t uniqueNum; @@ -105,8 +107,9 @@ namespace { public: static char ID; - explicit CppWriter(formatted_raw_ostream &o) : - ModulePass(ID), Out(o), uniqueNum(0), is_inline(false), indent_level(0){} + explicit CppWriter(std::unique_ptr o) + : ModulePass(ID), OutOwner(std::move(o)), Out(*OutOwner), uniqueNum(0), + is_inline(false), indent_level(0) {} const char *getPassName() const override { return "C++ backend"; } @@ -2146,13 +2149,14 @@ char CppWriter::ID = 0; // External Interface declaration //===----------------------------------------------------------------------===// -bool CPPTargetMachine::addPassesToEmitFile(PassManagerBase &PM, - formatted_raw_ostream &o, +bool CPPTargetMachine::addPassesToEmitFile(PassManagerBase &PM, raw_ostream &o, CodeGenFileType FileType, bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) { - if (FileType != TargetMachine::CGFT_AssemblyFile) return true; - PM.add(new CppWriter(o)); + if (FileType != TargetMachine::CGFT_AssemblyFile) + return true; + auto FOut = llvm::make_unique(o); + PM.add(new CppWriter(std::move(FOut))); return false; } diff --git a/lib/Target/CppBackend/CPPTargetMachine.h b/lib/Target/CppBackend/CPPTargetMachine.h index 678a932cb28..04f81e9e966 100644 --- a/lib/Target/CppBackend/CPPTargetMachine.h +++ b/lib/Target/CppBackend/CPPTargetMachine.h @@ -29,7 +29,7 @@ struct CPPTargetMachine : public TargetMachine { : TargetMachine(T, "", TT, CPU, FS, Options) {} public: - bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, + bool addPassesToEmitFile(PassManagerBase &PM, raw_ostream &Out, CodeGenFileType FileType, bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) override; diff --git a/lib/Target/TargetMachineC.cpp b/lib/Target/TargetMachineC.cpp index aaa66d3bf61..afba80f0f05 100644 --- a/lib/Target/TargetMachineC.cpp +++ b/lib/Target/TargetMachineC.cpp @@ -183,7 +183,7 @@ void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T, } static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M, - formatted_raw_ostream &OS, + raw_ostream &OS, LLVMCodeGenFileType codegen, char **ErrorMessage) { TargetMachine* TM = unwrap(T); @@ -231,8 +231,7 @@ LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, *ErrorMessage = strdup(EC.message().c_str()); return true; } - formatted_raw_ostream destf(dest); - bool Result = LLVMTargetMachineEmit(T, M, destf, codegen, ErrorMessage); + bool Result = LLVMTargetMachineEmit(T, M, dest, codegen, ErrorMessage); dest.flush(); return Result; } @@ -242,8 +241,7 @@ LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMMemoryBufferRef *OutMemBuf) { SmallString<0> CodeString; raw_svector_ostream OStream(CodeString); - formatted_raw_ostream Out(OStream); - bool Result = LLVMTargetMachineEmit(T, M, Out, codegen, ErrorMessage); + bool Result = LLVMTargetMachineEmit(T, M, OStream, codegen, ErrorMessage); OStream.flush(); StringRef Data = OStream.str(); diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 93ce3bc0f44..2c7bf5a64ee 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -31,7 +31,7 @@ #include "llvm/Linker/Linker.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/IRObjectFile.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" @@ -804,9 +804,8 @@ static void codegen(Module &M) { { raw_fd_ostream OS(FD, true); - formatted_raw_ostream FOS(OS); - if (TM->addPassesToEmitFile(CodeGenPasses, FOS, + if (TM->addPassesToEmitFile(CodeGenPasses, OS, TargetMachine::CGFT_ObjectFile)) message(LDPL_FATAL, "Failed to setup codegen"); CodeGenPasses.run(M); diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index d46cbb3181b..c20adfd9021 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -335,8 +335,6 @@ static int compileModule(char **argv, LLVMContext &Context) { << ": warning: ignoring -mc-relax-all because filetype != obj"; { - formatted_raw_ostream FOS(Out->os()); - AnalysisID StartAfterID = nullptr; AnalysisID StopAfterID = nullptr; const PassRegistry *PR = PassRegistry::getPassRegistry(); @@ -358,7 +356,7 @@ static int compileModule(char **argv, LLVMContext &Context) { } // Ask the target to add backend passes as necessary. - if (Target->addPassesToEmitFile(PM, FOS, FileType, NoVerify, + if (Target->addPassesToEmitFile(PM, Out->os(), FileType, NoVerify, StartAfterID, StopAfterID)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 9944f184ce8..58fe233fce1 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -439,7 +439,6 @@ int main(int argc, char **argv) { if (!Out) return 1; - formatted_raw_ostream FOS(Out->os()); std::unique_ptr Str; std::unique_ptr MCII(TheTarget->createMCInstrInfo()); @@ -461,9 +460,10 @@ int main(int argc, char **argv) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); } - Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/ true, - /*useDwarfDirectory*/ true, IP, CE, - MAB, ShowInst)); + auto FOut = llvm::make_unique(Out->os()); + Str.reset(TheTarget->createAsmStreamer( + Ctx, std::move(FOut), /*asmverbose*/ true, + /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); } else if (FileType == OFT_Null) { Str.reset(TheTarget->createNullStreamer(Ctx)); @@ -471,8 +471,8 @@ int main(int argc, char **argv) { assert(FileType == OFT_ObjectFile && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); - Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, FOS, CE, - *STI, RelaxAll, + Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, Out->os(), + CE, *STI, RelaxAll, /*DWARFMustBeAtTheEnd*/ false)); if (NoExecStack) Str->InitSections(true);