Index: include/llvm/MC/MCAsmInfo.h =================================================================== --- include/llvm/MC/MCAsmInfo.h +++ include/llvm/MC/MCAsmInfo.h @@ -356,6 +356,9 @@ /// construction (see LLVMTargetMachine::initAsmInfo()). bool UseIntegratedAssembler; + /// Preserve Comments in assembly + bool PreserveAsmComments; + /// Compress DWARF debug sections. Defaults to false. bool CompressDebugSections; @@ -565,6 +568,14 @@ 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; + } + bool compressDebugSections() const { return CompressDebugSections; } void setCompressDebugSections(bool CompressDebugSections) { Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -252,7 +252,7 @@ /// 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 @@ /// 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 explicit comments + virtual void outputExplicitComments(); + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. virtual void AddBlankLine() {} Index: include/llvm/Target/TargetOptions.h =================================================================== --- include/llvm/Target/TargetOptions.h +++ include/llvm/Target/TargetOptions.h @@ -96,8 +96,8 @@ UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false), GuaranteedTailCallOpt(false), StackAlignmentOverride(0), - StackSymbolOrdering(true), EnableFastISel(false), - UseInitArray(false), DisableIntegratedAS(false), + StackSymbolOrdering(true), EnableFastISel(false), UseInitArray(false), + DisableIntegratedAS(false), PreserveAsmComments(true), CompressDebugSections(false), FunctionSections(false), DataSections(false), UniqueSectionNames(true), TrapUnreachable(false), EmulatedTLS(false), FloatABIType(FloatABI::Default), @@ -186,6 +186,9 @@ /// Disable the integrated assembler. unsigned DisableIntegratedAS : 1; + /// Disable the integrated assembler. + unsigned PreserveAsmComments : 1; + /// Compress DWARF debug sections. unsigned CompressDebugSections : 1; Index: lib/CodeGen/LLVMTargetMachine.cpp =================================================================== --- lib/CodeGen/LLVMTargetMachine.cpp +++ lib/CodeGen/LLVMTargetMachine.cpp @@ -69,6 +69,8 @@ if (Options.DisableIntegratedAS) TmpAsmInfo->setUseIntegratedAssembler(false); + TmpAsmInfo->setPreserveAsmComments(Options.PreserveAsmComments); + if (Options.CompressDebugSections) TmpAsmInfo->setCompressDebugSections(true); Index: lib/MC/MCAsmInfo.cpp =================================================================== --- lib/MC/MCAsmInfo.cpp +++ lib/MC/MCAsmInfo.cpp @@ -107,6 +107,7 @@ // architecture basis. // - The target subclasses for AArch64, ARM, and X86 handle these cases UseIntegratedAssembler = false; + PreserveAsmComments = true; CompressDebugSections = false; } Index: lib/MC/MCAsmStreamer.cpp =================================================================== --- lib/MC/MCAsmStreamer.cpp +++ lib/MC/MCAsmStreamer.cpp @@ -45,6 +45,7 @@ std::unique_ptr Emitter; std::unique_ptr AsmBackend; + SmallString<128> ExplicitCommentToEmit; SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; @@ -72,6 +73,8 @@ } inline void EmitEOL() { + // Dump Explicit Comments here. + outputExplicitComments(); // If we don't have any comments, just emit a \n. if (!IsVerboseAsm) { OS << '\n'; @@ -111,6 +114,9 @@ void emitRawComment(const Twine &T, bool TabPrefix = true) override; + void addExplicitComment(const Twine &T) override; + void outputExplicitComments() override; + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. void AddBlankLine() override { EmitEOL(); @@ -314,6 +320,21 @@ EmitEOL(); } +void MCAsmStreamer::addExplicitComment(const Twine &T) { + StringRef c = T.getSingleStringRef(); + ExplicitCommentToEmit.append(c.str()); + // full line comments immediately output + if (c.back() == '\n') + outputExplicitComments(); +} + +void MCAsmStreamer::outputExplicitComments() { + StringRef Comments = ExplicitCommentToEmit; + if (!Comments.empty()) + OS << '\t' << Comments; + ExplicitCommentToEmit.clear(); +} + void MCAsmStreamer::ChangeSection(MCSection *Section, const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -624,8 +624,11 @@ const AsmToken &AsmParser::Lex() { const AsmToken *tok = &Lexer.Lex(); - // Parse 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(); } Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -70,6 +70,9 @@ void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {} +void MCStreamer::addExplicitComment(const Twine &T) {} +void MCStreamer::outputExplicitComments() {} + void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) { for (auto &FI : DwarfFrameInfos) FI.CompactUnwindEncoding = Index: test/MC/AsmParser/inline-comments.ll =================================================================== --- /dev/null +++ test/MC/AsmParser/inline-comments.ll @@ -0,0 +1,79 @@ +; 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 "//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)"} Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -68,6 +68,10 @@ NoIntegratedAssembler("no-integrated-as", cl::Hidden, cl::desc("Disable integrated assembler")); +static cl::opt + NoPreserveComments("fno-preserve-as-comments", cl::Hidden, + cl::desc("Preserve Comments in outputted assembly")); + // Determine optimization level. static cl::opt OptLevel("O", @@ -289,6 +293,7 @@ TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); Options.DisableIntegratedAS = NoIntegratedAssembler; + Options.PreserveAsmComments = !NoPreserveComments; Options.MCOptions.ShowMCEncoding = ShowMCEncoding; Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory; Options.MCOptions.AsmVerbose = AsmVerbose; Index: tools/llvm-mc/llvm-mc.cpp =================================================================== --- tools/llvm-mc/llvm-mc.cpp +++ tools/llvm-mc/llvm-mc.cpp @@ -74,6 +74,10 @@ static cl::list DefineSymbol("defsym", cl::desc("Defines a symbol to be an integer constant")); +static cl::opt + PreserveComments("preserve-comments", + cl::desc("Preserve Comments in outputted assembly")); + enum OutputFileType { OFT_Null, OFT_AssemblyFile, @@ -427,6 +431,7 @@ } MAI->setCompressDebugSections(true); } + 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.