diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 5470ab2f271..0842a24962c 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -90,6 +90,11 @@ namespace llvm { /// prefix as appropriate. The added comment should not end with a \n. virtual void AddComment(const Twine &T) {} + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS(); + /// @name Symbol & Section Management /// @{ diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index d3c45c244d1..05794e58988 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -456,6 +456,9 @@ public: explicit raw_svector_ostream(SmallVectorImpl &O); ~raw_svector_ostream(); + /// clear - Flush the stream and clear the underlying vector. + void clear(); + /// str - Flushes the stream contents to the target vector and return a /// StringRef for the vector contents. StringRef str(); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 5564fa16597..3f0a9def7fe 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1126,16 +1126,12 @@ static void EmitGlobalConstantStruct(const ConstantStruct *CS, static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, AsmPrinter &AP) { - SmallString<128> TmpBuffer; - // FP Constants are printed as integer constants to avoid losing // precision. if (CFP->getType()->isDoubleTy()) { if (AP.VerboseAsm) { - raw_svector_ostream OS(TmpBuffer); - double Val = CFP->getValueAPF().convertToDouble(); // for comment only - OS << "double " << Val; - AP.OutStreamer.AddComment(OS.str()); + double Val = CFP->getValueAPF().convertToDouble(); + AP.OutStreamer.GetCommentOS() << "double " << Val << '\n'; } uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 2c2fb0e8c20..4eb1bcdfb81 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -34,20 +34,23 @@ class MCAsmStreamer : public MCStreamer { MCCodeEmitter *Emitter; SmallString<128> CommentToEmit; + raw_svector_ostream CommentStream; public: MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, const MCAsmInfo &mai, bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer, MCCodeEmitter *emitter) : MCStreamer(Context), OS(os), MAI(mai), IsLittleEndian(isLittleEndian), - IsVerboseAsm(isVerboseAsm), InstPrinter(printer), Emitter(emitter) {} + IsVerboseAsm(isVerboseAsm), InstPrinter(printer), Emitter(emitter), + CommentStream(CommentToEmit) {} ~MCAsmStreamer() {} bool isLittleEndian() const { return IsLittleEndian; } inline void EmitEOL() { - if (CommentToEmit.empty()) { + // If we don't have any comments, just emit a \n. + if (!IsVerboseAsm) { OS << '\n'; return; } @@ -61,6 +64,15 @@ public: /// verbose assembly output is enabled. virtual void AddComment(const Twine &T); + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS() { + if (!IsVerboseAsm) + return nulls(); // Discard comments unless in verbose asm mode. + return CommentStream; + } + /// @name MCStreamer Interface /// @{ @@ -112,25 +124,36 @@ public: /// verbose assembly output is enabled. void MCAsmStreamer::AddComment(const Twine &T) { if (!IsVerboseAsm) return; - // Each comment goes on its own line. - if (!CommentToEmit.empty()) - CommentToEmit.push_back('\n'); + + // Make sure that CommentStream is flushed. + CommentStream.flush(); + T.toVector(CommentToEmit); + // Each comment goes on its own line. + CommentToEmit.push_back('\n'); } void MCAsmStreamer::EmitCommentsAndEOL() { + if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { + OS << '\n'; + return; + } + + CommentStream.flush(); StringRef Comments = CommentToEmit.str(); - while (!Comments.empty()) { + + assert(Comments.back() == '\n' && + "Comment array not newline terminated"); + do { // Emit a line of comments. OS.PadToColumn(MAI.getCommentColumn()); size_t Position = Comments.find('\n'); OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n'; - if (Position == StringRef::npos) break; Comments = Comments.substr(Position+1); - } + } while (!Comments.empty()); - CommentToEmit.clear(); + CommentStream.clear(); } diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 4e9d094550a..15b30794d91 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -9,7 +9,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" - +#include "llvm/Support/raw_ostream.h" using namespace llvm; MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) { @@ -18,6 +18,12 @@ MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) { MCStreamer::~MCStreamer() { } +raw_ostream &MCStreamer::GetCommentOS() { + // By default, discard comments. + return nulls(); +} + + /// EmitIntValue - Special case of EmitValue that avoids the client having to /// pass in a MCExpr for constant integers. void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size, diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index a820210f7bd..7cd16c888b9 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -562,6 +562,14 @@ raw_svector_ostream::~raw_svector_ostream() { flush(); } +/// clear - Flush the stream and clear the underlying vector. +void raw_svector_ostream::clear() { + if (GetNumBytesInBuffer() == 0) flush(); + + OS.clear(); + SetBuffer(OS.end(), OS.capacity() - OS.size()); +} + void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { assert(Ptr == OS.end() && OS.size() + Size <= OS.capacity() && "Invalid write_impl() call!");