diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index a405932bead..51f55109c9c 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -354,9 +354,12 @@ namespace llvm { /// isBlockOnlyReachableByFallthough - Return true if the basic block has /// exactly one predecessor and the control transfer mechanism between /// the predecessor and this block is a fall-through. - virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + virtual bool + isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; private: + /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. + void EmitInlineAsm(StringRef Str); /// processDebugLoc - Processes the debug information of each machine /// instruction's DebugLoc. diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index bdcfdb2debe..d42342c145e 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -62,9 +62,13 @@ class TargetAsmBackend; /// @name Assembly File Formatting. /// @{ - /// isVerboseAsm - Return true if this streamer supports verbose assembly at - /// all. + /// isVerboseAsm - Return true if this streamer supports verbose assembly + /// and if it is enabled. virtual bool isVerboseAsm() const { return false; } + + /// hasRawTextSupport - Return true if this asm streamer supports emitting + /// unformatted text to the .s file with EmitRawText. + virtual bool hasRawTextSupport() const { return false; } /// AddComment - Add a comment that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler @@ -278,6 +282,11 @@ class TargetAsmBackend; /// section. virtual void EmitInstruction(const MCInst &Inst) = 0; + /// EmitRawText - If this file is backed by a assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. By default this aborts. + virtual void EmitRawText(StringRef String); + /// Finish - Finish emission of machine code and flush any output. virtual void Finish() = 0; }; diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 2cb4d01574a..0d6a2e2999b 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -125,14 +125,12 @@ bool AsmPrinter::doInitialization(Module &M) { for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) MP->beginAssembly(O, *this, *MAI); - + + // Emit module-level inline asm if it exists. if (!M.getModuleInlineAsm().empty()) { OutStreamer.AddComment("Start of file scope inline assembly"); OutStreamer.AddBlankLine(); - O << M.getModuleInlineAsm(); - - if (*M.getModuleInlineAsm().rbegin() != '\n') - OutStreamer.AddBlankLine(); + EmitInlineAsm(M.getModuleInlineAsm()); OutStreamer.AddComment("End of file scope inline assembly"); OutStreamer.AddBlankLine(); } @@ -879,6 +877,22 @@ void AsmPrinter::EmitXXStructorList(Constant *List) { } } +/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. +void AsmPrinter::EmitInlineAsm(StringRef Str) { + assert(!Str.empty() && "Can't emit empty inline asm block"); + + // If the output streamer is actually a .s file, just emit the blob textually. + // This is useful in case the asm parser doesn't handle something but the + // system assembler does. + if (OutStreamer.hasRawTextSupport()) { + OutStreamer.EmitRawText(Str); + return; + } + + errs() << "Inline asm not supported by this streamer!\n"; +} + + //===--------------------------------------------------------------------===// // Emission and print routines // diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 7a23aecf297..b92051791a0 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -68,6 +68,9 @@ public: /// isVerboseAsm - Return true if this streamer supports verbose assembly at /// all. virtual bool isVerboseAsm() const { return IsVerboseAsm; } + + /// hasRawTextSupport - We support EmitRawText. + virtual bool hasRawTextSupport() const { return true; } /// AddComment - Add a comment that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler @@ -145,6 +148,11 @@ public: virtual void EmitInstruction(const MCInst &Inst); + /// EmitRawText - If this file is backed by a assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. + virtual void EmitRawText(StringRef String); + virtual void Finish(); /// @} @@ -195,7 +203,6 @@ void MCAsmStreamer::EmitCommentsAndEOL() { CommentStream.resync(); } - static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { assert(Bytes && "Invalid size!"); return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); @@ -634,6 +641,19 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { EmitEOL(); } +/// EmitRawText - If this file is backed by a assembly streamer, this dumps +/// the specified string in the output .s file. This capability is +/// indicated by the hasRawTextSupport() predicate. +void MCAsmStreamer::EmitRawText(StringRef String) { + if (!CommentToEmit.empty() || CommentStream.GetNumBytesInBuffer() != 0) + EmitCommentsAndEOL(); + + OS << String; + + if (!String.empty() && String.back() != '\n') + OS << '\n'; +} + void MCAsmStreamer::Finish() { OS.flush(); } diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 703acc4e599..c30dde8aed4 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -44,3 +44,12 @@ void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, for (uint64_t i = 0, e = NumBytes; i != e; ++i) EmitValue(E, 1, AddrSpace); } + +/// EmitRawText - If this file is backed by a assembly streamer, this dumps +/// the specified string in the output .s file. This capability is +/// indicated by the hasRawTextSupport() predicate. +void MCStreamer::EmitRawText(StringRef String) { + errs() << "EmitRawText called on an MCStreamer that doesn't support it, " + " something must not be fully mc'ized\n"; + abort(); +}