diff options
| -rw-r--r-- | llvm/include/llvm/MC/MCAsmInfo.h | 11 | ||||
| -rw-r--r-- | llvm/include/llvm/MC/MCStreamer.h | 8 | ||||
| -rw-r--r-- | llvm/include/llvm/MC/MCTargetOptions.h | 4 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/LLVMTargetMachine.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/MC/MCAsmInfo.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 55 | ||||
| -rw-r--r-- | llvm/lib/MC/MCParser/AsmParser.cpp | 13 | ||||
| -rw-r--r-- | llvm/lib/MC/MCParser/ELFAsmParser.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/MC/MCStreamer.cpp | 3 | ||||
| -rw-r--r-- | llvm/test/MC/AsmParser/inline-comments.ll | 88 | ||||
| -rw-r--r-- | llvm/test/MC/AsmParser/preserve-comments.s | 9 | ||||
| -rw-r--r-- | llvm/tools/llc/llc.cpp | 5 | ||||
| -rw-r--r-- | llvm/tools/llvm-mc/llvm-mc.cpp | 5 |
13 files changed, 201 insertions, 4 deletions
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h index 41f78e970ac..e6ed5688d18 100644 --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -362,6 +362,9 @@ protected: /// construction (see LLVMTargetMachine::initAsmInfo()). bool UseIntegratedAssembler; + /// Preserve Comments in assembly + bool PreserveAsmComments; + /// Compress DWARF debug sections. Defaults to no compression. DebugCompressionType CompressDebugSections; @@ -575,6 +578,14 @@ public: UseIntegratedAssembler = Value; } + /// Return true if assembly (inline or otherwise) should be parsed. + bool preserveAsmComments() const { return PreserveAsmComments; } + + /// Set whether assembly (inline or otherwise) should be parsed. + virtual void setPreserveAsmComments(bool Value) { + PreserveAsmComments = Value; + } + DebugCompressionType compressDebugSections() const { return CompressDebugSections; } diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 55ba12bbb65..cd710ee4342 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -252,7 +252,7 @@ public: /// correctly? virtual bool isIntegratedAssemblerRequired() const { return false; } - /// \brief Add a textual command. + /// \brief Add a textual comment. /// /// Typically for comments that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler @@ -274,6 +274,12 @@ public: /// only prints comments, the object streamer ignores it instead of asserting. virtual void emitRawComment(const Twine &T, bool TabPrefix = true); + /// \brief Add explicit comment T. T is required to be a valid + /// comment in the output and does not need to be escaped. + virtual void addExplicitComment(const Twine &T); + /// \brief Emit added explicit comments. + virtual void emitExplicitComments(); + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. virtual void AddBlankLine() {} diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h index 4b66a750cb7..1d170b757cb 100644 --- a/llvm/include/llvm/MC/MCTargetOptions.h +++ b/llvm/include/llvm/MC/MCTargetOptions.h @@ -36,6 +36,10 @@ public: bool ShowMCEncoding : 1; bool ShowMCInst : 1; bool AsmVerbose : 1; + + /// Preserve Comments in Assembly. + bool PreserveAsmComments : 1; + int DwarfVersion; /// getABIName - If this returns a non-empty string this represents the /// textual name of the ABI that we want the backend to use, e.g. o32, or diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp index f6f9b740957..e62c94dfd0a 100644 --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -70,6 +70,8 @@ void LLVMTargetMachine::initAsmInfo() { if (Options.DisableIntegratedAS) TmpAsmInfo->setUseIntegratedAssembler(false); + TmpAsmInfo->setPreserveAsmComments(Options.MCOptions.PreserveAsmComments); + if (Options.CompressDebugSections) TmpAsmInfo->setCompressDebugSections(DebugCompressionType::DCT_ZlibGnu); diff --git a/llvm/lib/MC/MCAsmInfo.cpp b/llvm/lib/MC/MCAsmInfo.cpp index fa83e395f8d..4a05175fdec 100644 --- a/llvm/lib/MC/MCAsmInfo.cpp +++ b/llvm/lib/MC/MCAsmInfo.cpp @@ -107,6 +107,7 @@ MCAsmInfo::MCAsmInfo() { // architecture basis. // - The target subclasses for AArch64, ARM, and X86 handle these cases UseIntegratedAssembler = false; + PreserveAsmComments = true; CompressDebugSections = DebugCompressionType::DCT_None; } diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 3ff66ed395b..6b089bcd313 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -46,6 +46,7 @@ class MCAsmStreamer final : public MCStreamer { std::unique_ptr<MCCodeEmitter> Emitter; std::unique_ptr<MCAsmBackend> AsmBackend; + SmallString<128> ExplicitCommentToEmit; SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; @@ -73,6 +74,8 @@ public: } inline void EmitEOL() { + // Dump Explicit Comments here. + emitExplicitComments(); // If we don't have any comments, just emit a \n. if (!IsVerboseAsm) { OS << '\n'; @@ -112,6 +115,9 @@ public: void emitRawComment(const Twine &T, bool TabPrefix = true) override; + void addExplicitComment(const Twine &T) override; + void emitExplicitComments() override; + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. void AddBlankLine() override { EmitEOL(); @@ -325,6 +331,49 @@ void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) { EmitEOL(); } +void MCAsmStreamer::addExplicitComment(const Twine &T) { + StringRef c = T.getSingleStringRef(); + if (c.equals(StringRef(MAI->getSeparatorString()))) + return; + if (c.startswith(StringRef("//"))) { + ExplicitCommentToEmit.append("\t"); + ExplicitCommentToEmit.append(MAI->getCommentString()); + // drop // + ExplicitCommentToEmit.append(c.slice(2, c.size()).str()); + } else if (c.startswith(StringRef("/*"))) { + size_t p = 2, len = c.size() - 2; + // emit each line in comment as separate newline. + do { + size_t newp = std::min(len, c.find_first_of("\r\n", p)); + ExplicitCommentToEmit.append("\t"); + ExplicitCommentToEmit.append(MAI->getCommentString()); + ExplicitCommentToEmit.append(c.slice(p, newp).str()); + // If we have another line in this comment add line + if (newp < len) + ExplicitCommentToEmit.append("\n"); + p = newp + 1; + } while (p < len); + } else if (c.startswith(StringRef(MAI->getCommentString()))) { + ExplicitCommentToEmit.append("\t"); + ExplicitCommentToEmit.append(c.str()); + } else if (c.front() == '#') { + // # are comments for ## commentString. Output extra #. + ExplicitCommentToEmit.append("\t#"); + ExplicitCommentToEmit.append(c.str()); + } else + assert(false && "Unexpected Assembly Comment"); + // full line comments immediately output + if (c.back() == '\n') + emitExplicitComments(); +} + +void MCAsmStreamer::emitExplicitComments() { + StringRef Comments = ExplicitCommentToEmit; + if (!Comments.empty()) + OS << Comments; + ExplicitCommentToEmit.clear(); +} + void MCAsmStreamer::ChangeSection(MCSection *Section, const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); @@ -510,8 +559,10 @@ void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { } void MCAsmStreamer::EmitSyntaxDirective() { - if (MAI->getAssemblerDialect() == 1) - OS << "\t.intel_syntax noprefix\n"; + if (MAI->getAssemblerDialect() == 1) { + OS << "\t.intel_syntax noprefix"; + EmitEOL(); + } // FIXME: Currently emit unprefix'ed registers. // The intel_syntax directive has one optional argument // with may have a value of prefix or noprefix. diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 9a331ec4458..d16f2452e13 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -626,9 +626,20 @@ const AsmToken &AsmParser::Lex() { if (Lexer.getTok().is(AsmToken::Error)) Error(Lexer.getErrLoc(), Lexer.getErr()); + // if it's a end of statement with a comment in it + if (getTok().is(AsmToken::EndOfStatement)) { + // if this is a line comment output it. + if (getTok().getString().front() != '\n' && + getTok().getString().front() != '\r' && MAI.preserveAsmComments()) + Out.addExplicitComment(Twine(getTok().getString())); + } + const AsmToken *tok = &Lexer.Lex(); - // Drop comments here. + + // Parse comments here to be deferred until end of next statement. while (tok->is(AsmToken::Comment)) { + if (MAI.preserveAsmComments()) + Out.addExplicitComment(Twine(tok->getString())); tok = &Lexer.Lex(); } diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp index 5650373a12d..533ae1f134b 100644 --- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -188,6 +188,7 @@ bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, if (getParser().parseExpression(Subsection)) return true; } + Lex(); getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags), Subsection); diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 9ef96695e89..6c8828f71ba 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -70,6 +70,9 @@ raw_ostream &MCStreamer::GetCommentOS() { void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {} +void MCStreamer::addExplicitComment(const Twine &T) {} +void MCStreamer::emitExplicitComments() {} + void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) { for (auto &FI : DwarfFrameInfos) FI.CompactUnwindEncoding = diff --git a/llvm/test/MC/AsmParser/inline-comments.ll b/llvm/test/MC/AsmParser/inline-comments.ll new file mode 100644 index 00000000000..b0699d44ebb --- /dev/null +++ b/llvm/test/MC/AsmParser/inline-comments.ll @@ -0,0 +1,88 @@ +; RUN: llc %s -o - | sed -n -e '/#APP/,/#NO_APP/p' > %t +; RUN: sed -n -e 's/^;CHECK://p' %s > %t2 +; RUN: diff %t %t2 + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define void @foo() #0 { +entry: + call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: #NO_APP + call void asm sideeffect " ", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: +;CHECK: #NO_APP + call void asm sideeffect "\0A", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: +;CHECK: +;CHECK: #NO_APP + call void asm sideeffect "/*isolated c comment*/", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: #isolated c comment +;CHECK: #NO_APP + call void asm sideeffect "/**/", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: # +;CHECK: #NO_APP + call void asm sideeffect "/*comment with\0Anewline*/", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: #comment with +;CHECK: #newline +;CHECK: #NO_APP + call void asm sideeffect "//isolated line comment", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: #isolated line comment +;CHECK: #NO_APP + call void asm sideeffect "#isolated line comment", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: #isolated line comment +;CHECK: #NO_APP + call void asm sideeffect "nop /* after nop */", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: nop # after nop +;CHECK: #NO_APP + call void asm sideeffect "nop // after nop", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: nop # after nop +;CHECK: #NO_APP + call void asm sideeffect "nop # after nop", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: nop # after nop +;CHECK: #NO_APP + call void asm sideeffect "nop /* after explicit ended nop */", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: nop # after explicit ended nop +;CHECK: #NO_APP + call void asm sideeffect "nop # after explicit ended nop", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: nop # after explicit ended nop +;CHECK: #NO_APP + call void asm sideeffect "nop # after explicit end nop", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: nop # after explicit end nop +;CHECK: #NO_APP + call void asm sideeffect "/* before nop */ nop", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: nop # before nop +;CHECK: #NO_APP + call void asm sideeffect "//comment with escaped newline\0A", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: #comment with escaped newline +;CHECK: +;CHECK: #NO_APP + call void asm sideeffect "/*0*/xor/*1*/%eax,/*2*/%ecx/*3*///eol", "~{dirflag},~{fpsr},~{flags}"() #0 +;CHECK: #APP +;CHECK: xorl %eax, %ecx #0 #1 #2 #3 #eol +;CHECK: #NO_APP + ret void +} + +attributes #0 = { nounwind } + +!llvm.ident = !{!0} + +!0 = !{!"clang version 3.9.0 (trunk 268625) (llvm/trunk 268631)"} diff --git a/llvm/test/MC/AsmParser/preserve-comments.s b/llvm/test/MC/AsmParser/preserve-comments.s new file mode 100644 index 00000000000..2ff5b7b9867 --- /dev/null +++ b/llvm/test/MC/AsmParser/preserve-comments.s @@ -0,0 +1,9 @@ + #RUN: llvm-mc -preserve-comments -n -triple i386-linux-gnu < %s > %t + #RUN: diff %s %t + .text + + nop + #if DIRECTIVE COMMENT + ## WHOLE LINE COMMENT + cmpl $196, %eax ## EOL COMMENT + #endif diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index 1e7cd1433c3..de4d1ab4ef7 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -73,6 +73,10 @@ static cl::opt<bool> NoIntegratedAssembler("no-integrated-as", cl::Hidden, cl::desc("Disable integrated assembler")); +static cl::opt<bool> + NoPreserveComments("fno-preserve-as-comments", cl::Hidden, + cl::desc("Preserve Comments in outputted assembly")); + // Determine optimization level. static cl::opt<char> OptLevel("O", @@ -332,6 +336,7 @@ static int compileModule(char **argv, LLVMContext &Context) { Options.MCOptions.ShowMCEncoding = ShowMCEncoding; Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory; Options.MCOptions.AsmVerbose = AsmVerbose; + Options.MCOptions.PreserveAsmComments = !NoPreserveComments; std::unique_ptr<TargetMachine> Target( TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr, FeaturesStr, diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index ad3a9d09e6e..00f19cb328c 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -87,6 +87,10 @@ PrintImmHex("print-imm-hex", cl::init(false), static cl::list<std::string> DefineSymbol("defsym", cl::desc("Defines a symbol to be an integer constant")); +static cl::opt<bool> + PreserveComments("preserve-comments", + cl::desc("Preserve Comments in outputted assembly")); + enum OutputFileType { OFT_Null, OFT_AssemblyFile, @@ -430,6 +434,7 @@ int main(int argc, char **argv) { } MAI->setCompressDebugSections(CompressDebugSections); } + MAI->setPreserveAsmComments(PreserveComments); // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. |

