llvm.org GIT mirror llvm / 427c073
Simplify use of formatted_raw_ostream. formatted_raw_ostream is a wrapper over another stream to add column and line number tracking. It is used only for asm printing. This patch moves the its creation down to where we know we are printing assembly. This has the following advantages: * Simpler lifetime management: std::unique_ptr * We don't compute column and line number of object files :-) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@234535 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 5 years ago
13 changed file(s) with 83 addition(s) and 103 deletion(s). Raw diff Collapse all Expand all
745745 ///
746746 /// \param ShowInst - Whether to show the MCInst representation inline with
747747 /// the assembly.
748 MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
748 MCStreamer *createAsmStreamer(MCContext &Ctx,
749 std::unique_ptr OS,
749750 bool isVerboseAsm, bool useDwarfDirectory,
750751 MCInstPrinter *InstPrint, MCCodeEmitter *CE,
751752 MCAsmBackend *TAB, bool ShowInst);
2424 /// boundaries and querying the number of lines written to the stream.
2525 ///
2626 class formatted_raw_ostream : public raw_ostream {
27 public:
28 /// DELETE_STREAM - Tell the destructor to delete the held stream.
29 ///
30 static const bool DELETE_STREAM = true;
31
32 /// PRESERVE_STREAM - Tell the destructor to not delete the held
33 /// stream.
34 ///
35 static const bool PRESERVE_STREAM = false;
36
37 private:
3827 /// TheStream - The real stream we output to. We set it to be
3928 /// unbuffered, since we're already doing our own buffering.
4029 ///
4130 raw_ostream *TheStream;
42
43 /// DeleteStream - Do we need to delete TheStream in the
44 /// destructor?
45 ///
46 bool DeleteStream;
4731
4832 /// Position - The current output column and line of the data that's
4933 /// been flushed and the portion of the buffer that's been
7256 ///
7357 void ComputePosition(const char *Ptr, size_t size);
7458
75 public:
76 /// formatted_raw_ostream - Open the specified file for
77 /// writing. If an error occurs, information about the error is
78 /// put into ErrorInfo, and the stream should be immediately
79 /// destroyed; the string will be empty if no error occurred.
80 ///
81 /// As a side effect, the given Stream is set to be Unbuffered.
82 /// This is because formatted_raw_ostream does its own buffering,
83 /// so it doesn't want another layer of buffering to be happening
84 /// underneath it.
85 ///
86 formatted_raw_ostream(raw_ostream &Stream, bool Delete = false)
87 : TheStream(nullptr), DeleteStream(false), Position(0, 0) {
88 setStream(Stream, Delete);
89 }
90 explicit formatted_raw_ostream()
91 : TheStream(nullptr), DeleteStream(false), Position(0, 0) {
92 Scanned = nullptr;
93 }
94
95 ~formatted_raw_ostream() {
96 flush();
97 releaseStream();
98 }
99
100 void setStream(raw_ostream &Stream, bool Delete = false) {
59 void setStream(raw_ostream &Stream) {
10160 releaseStream();
10261
10362 TheStream = &Stream;
104 DeleteStream = Delete;
10563
10664 // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
10765 // own buffering, and it doesn't need or want TheStream to do another
11472 TheStream->SetUnbuffered();
11573
11674 Scanned = nullptr;
75 }
76
77 public:
78 /// formatted_raw_ostream - Open the specified file for
79 /// writing. If an error occurs, information about the error is
80 /// put into ErrorInfo, and the stream should be immediately
81 /// destroyed; the string will be empty if no error occurred.
82 ///
83 /// As a side effect, the given Stream is set to be Unbuffered.
84 /// This is because formatted_raw_ostream does its own buffering,
85 /// so it doesn't want another layer of buffering to be happening
86 /// underneath it.
87 ///
88 formatted_raw_ostream(raw_ostream &Stream)
89 : TheStream(nullptr), Position(0, 0) {
90 setStream(Stream);
91 }
92 explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) {
93 Scanned = nullptr;
94 }
95
96 ~formatted_raw_ostream() {
97 flush();
98 releaseStream();
11799 }
118100
119101 /// PadToColumn - Align the output to some column number. If the current
150132
151133 private:
152134 void releaseStream() {
153 // Delete the stream if needed. Otherwise, transfer the buffer
154 // settings from this raw_ostream back to the underlying stream.
135 // Transfer the buffer settings from this raw_ostream back to the underlying
136 // stream.
155137 if (!TheStream)
156138 return;
157 if (DeleteStream)
158 delete TheStream;
159 else if (size_t BufferSize = GetBufferSize())
139 if (size_t BufferSize = GetBufferSize())
160140 TheStream->SetBufferSize(BufferSize);
161141 else
162142 TheStream->SetUnbuffered();
2121 #include "llvm-c/Disassembler.h"
2222 #include "llvm/ADT/Triple.h"
2323 #include "llvm/Support/CodeGen.h"
24 #include "llvm/Support/FormattedStream.h"
2425 #include
2526 #include
2627 #include
5152 class formatted_raw_ostream;
5253
5354 MCStreamer *createNullStreamer(MCContext &Ctx);
54 MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
55 MCStreamer *createAsmStreamer(MCContext &Ctx,
56 std::unique_ptr OS,
5557 bool isVerboseAsm, bool useDwarfDirectory,
5658 MCInstPrinter *InstPrint, MCCodeEmitter *CE,
5759 MCAsmBackend *TAB, bool ShowInst);
468470 return S;
469471 }
470472
471 MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
473 MCStreamer *createAsmStreamer(MCContext &Ctx,
474 std::unique_ptr OS,
472475 bool IsVerboseAsm, bool UseDwarfDirectory,
473476 MCInstPrinter *InstPrint, MCCodeEmitter *CE,
474477 MCAsmBackend *TAB, bool ShowInst) const {
475 MCStreamer *S =
476 llvm::createAsmStreamer(Ctx, OS, IsVerboseAsm, UseDwarfDirectory,
477 InstPrint, CE, TAB, ShowInst);
478 createAsmTargetStreamer(*S, OS, InstPrint, IsVerboseAsm);
478 formatted_raw_ostream &OSRef = *OS;
479 MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IsVerboseAsm,
480 UseDwarfDirectory, InstPrint, CE,
481 TAB, ShowInst);
482 createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm);
479483 return S;
480484 }
481485
206206 /// emitted. Typically this will involve several steps of code generation.
207207 /// This method should return true if emission of this file type is not
208208 /// supported, or false on success.
209 virtual bool addPassesToEmitFile(PassManagerBase &,
210 formatted_raw_ostream &,
209 virtual bool addPassesToEmitFile(PassManagerBase &, raw_ostream &,
211210 CodeGenFileType,
212211 bool /*DisableVerify*/ = true,
213212 AnalysisID /*StartAfter*/ = nullptr,
256255
257256 /// Add passes to the specified pass manager to get the specified file
258257 /// emitted. Typically this will involve several steps of code generation.
259 bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out,
258 bool addPassesToEmitFile(PassManagerBase &PM, raw_ostream &Out,
260259 CodeGenFileType FileType, bool DisableVerify = true,
261260 AnalysisID StartAfter = nullptr,
262261 AnalysisID StopAfter = nullptr) override;
139139 return &MMI->getContext();
140140 }
141141
142 bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
143 formatted_raw_ostream &Out,
144 CodeGenFileType FileType,
145 bool DisableVerify,
146 AnalysisID StartAfter,
147 AnalysisID StopAfter) {
142 bool LLVMTargetMachine::addPassesToEmitFile(
143 PassManagerBase &PM, raw_ostream &Out, CodeGenFileType FileType,
144 bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter) {
148145 // Add common CodeGen passes.
149146 MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,
150147 StartAfter, StopAfter);
183180
184181 MCAsmBackend *MAB = getTarget().createMCAsmBackend(MRI, getTargetTriple(),
185182 TargetCPU);
183 auto FOut = llvm::make_unique(Out);
186184 MCStreamer *S = getTarget().createAsmStreamer(
187 *Context, Out, Options.MCOptions.AsmVerbose,
185 *Context, std::move(FOut), Options.MCOptions.AsmVerbose,
188186 Options.MCOptions.MCUseDwarfDirectory, InstPrinter, MCE, MAB,
189187 Options.MCOptions.ShowMCInst);
190188 AsmStreamer.reset(S);
3737 #include "llvm/MC/SubtargetFeature.h"
3838 #include "llvm/Support/CommandLine.h"
3939 #include "llvm/Support/FileSystem.h"
40 #include "llvm/Support/FormattedStream.h"
4140 #include "llvm/Support/Host.h"
4241 #include "llvm/Support/MemoryBuffer.h"
4342 #include "llvm/Support/Signals.h"
573572
574573 legacy::PassManager codeGenPasses;
575574
576 formatted_raw_ostream Out(out);
577
578575 // If the bitcode files contain ARC code and were compiled with optimization,
579576 // the ObjCARCContractPass must be run, so do it unconditionally here.
580577 codeGenPasses.add(createObjCARCContractPass());
581578
582 if (TargetMach->addPassesToEmitFile(codeGenPasses, Out,
579 if (TargetMach->addPassesToEmitFile(codeGenPasses, out,
583580 TargetMachine::CGFT_ObjectFile)) {
584581 errMsg = "target file type not supported";
585582 return false;
3636 namespace {
3737
3838 class MCAsmStreamer final : public MCStreamer {
39 std::unique_ptr OSOwner;
3940 formatted_raw_ostream &OS;
4041 const MCAsmInfo *MAI;
4142 std::unique_ptr InstPrinter;
5455 void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
5556
5657 public:
57 MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
58 MCAsmStreamer(MCContext &Context, std::unique_ptr os,
5859 bool isVerboseAsm, bool useDwarfDirectory,
5960 MCInstPrinter *printer, MCCodeEmitter *emitter,
6061 MCAsmBackend *asmbackend, bool showInst)
61 : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()),
62 InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend),
63 CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
64 ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
62 : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
63 MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter),
64 AsmBackend(asmbackend), CommentStream(CommentToEmit),
65 IsVerboseAsm(isVerboseAsm), ShowInst(showInst),
66 UseDwarfDirectory(useDwarfDirectory) {
6567 if (InstPrinter && IsVerboseAsm)
6668 InstPrinter->setCommentStream(CommentStream);
6769 }
13111313 }
13121314
13131315 MCStreamer *llvm::createAsmStreamer(MCContext &Context,
1314 formatted_raw_ostream &OS,
1316 std::unique_ptr OS,
13151317 bool isVerboseAsm, bool useDwarfDirectory,
13161318 MCInstPrinter *IP, MCCodeEmitter *CE,
13171319 MCAsmBackend *MAB, bool ShowInst) {
1318 return new MCAsmStreamer(Context, OS, isVerboseAsm, useDwarfDirectory, IP, CE,
1319 MAB, ShowInst);
1320 }
1320 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
1321 useDwarfDirectory, IP, CE, MAB, ShowInst);
1322 }
1414 #include "CPPTargetMachine.h"
1515 #include "llvm/ADT/SmallPtrSet.h"
1616 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/STLExtras.h"
1718 #include "llvm/Config/config.h"
1819 #include "llvm/IR/CallingConv.h"
1920 #include "llvm/IR/Constants.h"
9091 /// CppWriter - This class is the main chunk of code that converts an LLVM
9192 /// module to a C++ translation unit.
9293 class CppWriter : public ModulePass {
94 std::unique_ptr OutOwner;
9395 formatted_raw_ostream &Out;
9496 const Module *TheModule;
9597 uint64_t uniqueNum;
104106
105107 public:
106108 static char ID;
107 explicit CppWriter(formatted_raw_ostream &o) :
108 ModulePass(ID), Out(o), uniqueNum(0), is_inline(false), indent_level(0){}
109 explicit CppWriter(std::unique_ptr o)
110 : ModulePass(ID), OutOwner(std::move(o)), Out(*OutOwner), uniqueNum(0),
111 is_inline(false), indent_level(0) {}
109112
110113 const char *getPassName() const override { return "C++ backend"; }
111114
21452148 // External Interface declaration
21462149 //===----------------------------------------------------------------------===//
21472150
2148 bool CPPTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
2149 formatted_raw_ostream &o,
2151 bool CPPTargetMachine::addPassesToEmitFile(PassManagerBase &PM, raw_ostream &o,
21502152 CodeGenFileType FileType,
21512153 bool DisableVerify,
21522154 AnalysisID StartAfter,
21532155 AnalysisID StopAfter) {
2154 if (FileType != TargetMachine::CGFT_AssemblyFile) return true;
2155 PM.add(new CppWriter(o));
2156 if (FileType != TargetMachine::CGFT_AssemblyFile)
2157 return true;
2158 auto FOut = llvm::make_unique(o);
2159 PM.add(new CppWriter(std::move(FOut)));
21562160 return false;
21572161 }
2828 : TargetMachine(T, "", TT, CPU, FS, Options) {}
2929
3030 public:
31 bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out,
31 bool addPassesToEmitFile(PassManagerBase &PM, raw_ostream &Out,
3232 CodeGenFileType FileType, bool DisableVerify,
3333 AnalysisID StartAfter,
3434 AnalysisID StopAfter) override;
182182 }
183183
184184 static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,
185 formatted_raw_ostream &OS,
185 raw_ostream &OS,
186186 LLVMCodeGenFileType codegen,
187187 char **ErrorMessage) {
188188 TargetMachine* TM = unwrap(T);
230230 *ErrorMessage = strdup(EC.message().c_str());
231231 return true;
232232 }
233 formatted_raw_ostream destf(dest);
234 bool Result = LLVMTargetMachineEmit(T, M, destf, codegen, ErrorMessage);
233 bool Result = LLVMTargetMachineEmit(T, M, dest, codegen, ErrorMessage);
235234 dest.flush();
236235 return Result;
237236 }
241240 LLVMMemoryBufferRef *OutMemBuf) {
242241 SmallString<0> CodeString;
243242 raw_svector_ostream OStream(CodeString);
244 formatted_raw_ostream Out(OStream);
245 bool Result = LLVMTargetMachineEmit(T, M, Out, codegen, ErrorMessage);
243 bool Result = LLVMTargetMachineEmit(T, M, OStream, codegen, ErrorMessage);
246244 OStream.flush();
247245
248246 StringRef Data = OStream.str();
3030 #include "llvm/Linker/Linker.h"
3131 #include "llvm/MC/SubtargetFeature.h"
3232 #include "llvm/Object/IRObjectFile.h"
33 #include "llvm/Support/FormattedStream.h"
33 #include "llvm/Support/raw_ostream.h"
3434 #include "llvm/Support/Host.h"
3535 #include "llvm/Support/ManagedStatic.h"
3636 #include "llvm/Support/MemoryBuffer.h"
803803
804804 {
805805 raw_fd_ostream OS(FD, true);
806 formatted_raw_ostream FOS(OS);
807
808 if (TM->addPassesToEmitFile(CodeGenPasses, FOS,
806
807 if (TM->addPassesToEmitFile(CodeGenPasses, OS,
809808 TargetMachine::CGFT_ObjectFile))
810809 message(LDPL_FATAL, "Failed to setup codegen");
811810 CodeGenPasses.run(M);
334334 << ": warning: ignoring -mc-relax-all because filetype != obj";
335335
336336 {
337 formatted_raw_ostream FOS(Out->os());
338
339337 AnalysisID StartAfterID = nullptr;
340338 AnalysisID StopAfterID = nullptr;
341339 const PassRegistry *PR = PassRegistry::getPassRegistry();
357355 }
358356
359357 // Ask the target to add backend passes as necessary.
360 if (Target->addPassesToEmitFile(PM, FOS, FileType, NoVerify,
358 if (Target->addPassesToEmitFile(PM, Out->os(), FileType, NoVerify,
361359 StartAfterID, StopAfterID)) {
362360 errs() << argv[0] << ": target does not support generation of this"
363361 << " file type!\n";
438438 if (!Out)
439439 return 1;
440440
441 formatted_raw_ostream FOS(Out->os());
442441 std::unique_ptr Str;
443442
444443 std::unique_ptr MCII(TheTarget->createMCInstrInfo());
460459 CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
461460 MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
462461 }
463 Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/ true,
464 /*useDwarfDirectory*/ true, IP, CE,
465 MAB, ShowInst));
462 auto FOut = llvm::make_unique(Out->os());
463 Str.reset(TheTarget->createAsmStreamer(
464 Ctx, std::move(FOut), /*asmverbose*/ true,
465 /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst));
466466
467467 } else if (FileType == OFT_Null) {
468468 Str.reset(TheTarget->createNullStreamer(Ctx));
470470 assert(FileType == OFT_ObjectFile && "Invalid file type!");
471471 MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
472472 MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
473 Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, FOS, CE,
474 *STI, RelaxAll,
473 Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, Out->os(),
474 CE, *STI, RelaxAll,
475475 /*DWARFMustBeAtTheEnd*/ false));
476476 if (NoExecStack)
477477 Str->InitSections(true);