summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirav Dave <niravd@google.com>2016-07-11 12:42:14 +0000
committerNirav Dave <niravd@google.com>2016-07-11 12:42:14 +0000
commitaee0f143c937f6721b74c2efd081d9ecac7f99c4 (patch)
treeb970b8b678a13fc4616ebcf6fda9d89955c395a7
parent20ad7302fa33c1a1498504140159afb58b4e50f8 (diff)
Provide support for preserving assembly comments
Preserve assembly comments from input in output assembly and flags to toggle property. This is on by default for inline assembly and off in llvm-mc. Parsed comments are emitted immediately before an EOL which generally places them on the expected line. Reviewers: rtrieu, dwmw2, rnk, majnemer Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D20020 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275058 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCAsmInfo.h11
-rw-r--r--include/llvm/MC/MCStreamer.h8
-rw-r--r--include/llvm/MC/MCTargetOptions.h4
-rw-r--r--lib/CodeGen/LLVMTargetMachine.cpp2
-rw-r--r--lib/MC/MCAsmInfo.cpp1
-rw-r--r--lib/MC/MCAsmStreamer.cpp55
-rw-r--r--lib/MC/MCParser/AsmParser.cpp13
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp1
-rw-r--r--lib/MC/MCStreamer.cpp3
-rw-r--r--test/MC/AsmParser/inline-comments.ll88
-rw-r--r--test/MC/AsmParser/preserve-comments.s9
-rw-r--r--tools/llc/llc.cpp5
-rw-r--r--tools/llvm-mc/llvm-mc.cpp5
13 files changed, 201 insertions, 4 deletions
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 41f78e970ac..e6ed5688d18 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/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/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 55ba12bbb65..cd710ee4342 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/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/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h
index 4b66a750cb7..1d170b757cb 100644
--- a/include/llvm/MC/MCTargetOptions.h
+++ b/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/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index f6f9b740957..e62c94dfd0a 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/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/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index fa83e395f8d..4a05175fdec 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/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/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 3ff66ed395b..6b089bcd313 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/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/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 9a331ec4458..d16f2452e13 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/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/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp
index 5650373a12d..533ae1f134b 100644
--- a/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/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/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 9ef96695e89..6c8828f71ba 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/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/test/MC/AsmParser/inline-comments.ll b/test/MC/AsmParser/inline-comments.ll
new file mode 100644
index 00000000000..b0699d44ebb
--- /dev/null
+++ b/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/test/MC/AsmParser/preserve-comments.s b/test/MC/AsmParser/preserve-comments.s
new file mode 100644
index 00000000000..2ff5b7b9867
--- /dev/null
+++ b/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/tools/llc/llc.cpp b/tools/llc/llc.cpp
index 1e7cd1433c3..de4d1ab4ef7 100644
--- a/tools/llc/llc.cpp
+++ b/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/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index ad3a9d09e6e..00f19cb328c 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/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.