aboutsummaryrefslogtreecommitdiff
path: root/lib/MC/MCAsmStreamer.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
commit01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch)
tree4def12e759965de927d963ac65840d663ef9d1ea /lib/MC/MCAsmStreamer.cpp
parentf0f4822ed4b66e3579e92a89f368f8fb860e218e (diff)
downloadsrc-01095a5d43bbfde13731688ddcf6048ebb8b7721.tar.gz
src-01095a5d43bbfde13731688ddcf6048ebb8b7721.zip
Vendor import of llvm release_39 branch r276489:vendor/llvm/llvm-release_39-r276489
Notes
Notes: svn path=/vendor/llvm/dist/; revision=303231 svn path=/vendor/llvm/llvm-release_39-r276489/; revision=303232; tag=vendor/llvm/llvm-release_39-r276489
Diffstat (limited to 'lib/MC/MCAsmStreamer.cpp')
-rw-r--r--lib/MC/MCAsmStreamer.cpp274
1 files changed, 242 insertions, 32 deletions
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index c99ce7752b30..ef2f7810deaa 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/MC/MCStreamer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -24,14 +23,15 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/SourceMgr.h"
#include <cctype>
using namespace llvm;
@@ -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();
@@ -162,6 +168,8 @@ public:
void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment = 0) override;
+ void EmitBinaryData(StringRef Data) override;
+
void EmitBytes(StringRef Data) override;
void EmitValueImpl(const MCExpr *Value, unsigned Size,
@@ -177,7 +185,15 @@ public:
void EmitGPRel32Value(const MCExpr *Value) override;
- void EmitFill(uint64_t NumBytes, uint8_t FillValue) override;
+ void emitFill(uint64_t NumBytes, uint8_t FillValue) override;
+
+ void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+ SMLoc Loc = SMLoc()) override;
+
+ void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) override;
+
+ void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
+ SMLoc Loc = SMLoc()) override;
void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
@@ -199,6 +215,22 @@ public:
StringRef FileName) override;
MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
+ unsigned EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
+ void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
+ unsigned Column, bool PrologueEnd, bool IsStmt,
+ StringRef FileName) override;
+ void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
+ const MCSymbol *FnEnd) override;
+ void EmitCVInlineLinetableDirective(
+ unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
+ const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
+ ArrayRef<unsigned> SecondaryFunctionIds) override;
+ void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ StringRef FixedSizePortion) override;
+ void EmitCVStringTableDirective() override;
+ void EmitCVFileChecksumsDirective() override;
+
void EmitIdent(StringRef IdentString) override;
void EmitCFISections(bool EH, bool Debug) override;
void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
@@ -288,7 +320,7 @@ void MCAsmStreamer::EmitCommentsAndEOL() {
}
static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
- assert(Bytes && "Invalid size!");
+ assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
}
@@ -299,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!");
@@ -326,12 +401,11 @@ void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
bool IsFirst = true;
- for (MCLOHArgs::const_iterator It = Args.begin(), EndIt = Args.end();
- It != EndIt; ++It) {
+ for (const MCSymbol *Arg : Args) {
if (!IsFirst)
OS << ", ";
IsFirst = false;
- (*It)->print(OS, MAI);
+ Arg->print(OS, MAI);
}
EmitEOL();
}
@@ -354,7 +428,7 @@ void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
ie = Options.end(); it != ie; ++it) {
OS << ", " << '"' << *it << '"';
}
- OS << "\n";
+ EmitEOL();
}
void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
@@ -456,6 +530,7 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
OS << "\t.no_dead_strip\t";
break;
case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
+ case MCSA_AltEntry: OS << "\t.alt_entry\t"; break;
case MCSA_PrivateExtern:
OS << "\t.private_extern\t";
break;
@@ -484,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.
@@ -537,7 +614,7 @@ void MCAsmStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) {
Symbol->print(OS, MAI);
OS << ", ";
Value->print(OS, MAI);
- OS << '\n';
+ EmitEOL();
}
void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@@ -684,6 +761,20 @@ void MCAsmStreamer::EmitBytes(StringRef Data) {
EmitEOL();
}
+void MCAsmStreamer::EmitBinaryData(StringRef Data) {
+ // This is binary data. Print it in a grid of hex bytes for readability.
+ const size_t Cols = 4;
+ for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
+ size_t J = I, EJ = std::min(I + Cols, Data.size());
+ assert(EJ > 0);
+ OS << MAI->getData8bitsDirective();
+ for (; J < EJ - 1; ++J)
+ OS << format("0x%02x", uint8_t(Data[J])) << ", ";
+ OS << format("0x%02x", uint8_t(Data[J]));
+ EmitEOL();
+ }
+}
+
void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
EmitValue(MCConstantExpr::create(Value, getContext()), Size);
}
@@ -708,17 +799,15 @@ void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
report_fatal_error("Don't know how to emit this value.");
// We couldn't handle the requested integer size so we fallback by breaking
- // the request down into several, smaller, integers. Since sizes greater
- // than eight are invalid and size equivalent to eight should have been
- // handled earlier, we use four bytes as our largest piece of granularity.
+ // the request down into several, smaller, integers.
+ // Since sizes greater or equal to "Size" are invalid, we use the greatest
+ // power of 2 that is less than "Size" as our largest piece of granularity.
bool IsLittleEndian = MAI->isLittleEndian();
for (unsigned Emitted = 0; Emitted != Size;) {
unsigned Remaining = Size - Emitted;
// The size of our partial emission must be a power of two less than
- // eight.
- unsigned EmissionSize = PowerOf2Floor(Remaining);
- if (EmissionSize > 4)
- EmissionSize = 4;
+ // Size.
+ unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
// Calculate the byte offset of our partial emission taking into account
// the endianness of the target.
unsigned ByteOffset =
@@ -780,21 +869,46 @@ void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
EmitEOL();
}
-/// EmitFill - Emit NumBytes bytes worth of the value specified by
+/// emitFill - Emit NumBytes bytes worth of the value specified by
/// FillValue. This implements directives such as '.space'.
-void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) {
+void MCAsmStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
if (NumBytes == 0) return;
+ const MCExpr *E = MCConstantExpr::create(NumBytes, getContext());
+ emitFill(*E, FillValue);
+}
+
+void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+ SMLoc Loc) {
if (const char *ZeroDirective = MAI->getZeroDirective()) {
- OS << ZeroDirective << NumBytes;
+ // FIXME: Emit location directives
+ OS << ZeroDirective;
+ NumBytes.print(OS, MAI);
if (FillValue != 0)
OS << ',' << (int)FillValue;
EmitEOL();
return;
}
- // Emit a byte at a time.
- MCStreamer::EmitFill(NumBytes, FillValue);
+ MCStreamer::emitFill(NumBytes, FillValue);
+}
+
+void MCAsmStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) {
+ if (NumValues == 0)
+ return;
+
+ const MCExpr *E = MCConstantExpr::create(NumValues, getContext());
+ emitFill(*E, Size, Expr);
+}
+
+void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
+ int64_t Expr, SMLoc Loc) {
+ // FIXME: Emit location directives
+ OS << "\t.fill\t";
+ NumValues.print(OS, MAI);
+ OS << ", " << Size << ", 0x";
+ OS.write_hex(truncateToSize(Expr, 4));
+ EmitEOL();
}
void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
@@ -807,7 +921,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
default:
llvm_unreachable("Invalid size for machine code value!");
case 1:
- OS << "\t.align\t";
+ OS << "\t.p2align\t";
break;
case 2:
OS << ".p2alignw ";
@@ -819,10 +933,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
llvm_unreachable("Unsupported alignment size!");
}
- if (MAI->getAlignmentIsInBytes())
- OS << ByteAlignment;
- else
- OS << Log2_32(ByteAlignment);
+ OS << Log2_32(ByteAlignment);
if (Value || MaxBytesToEmit) {
OS << ", 0x";
@@ -957,6 +1068,105 @@ MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
return MCStreamer::getDwarfLineTableSymbol(0);
}
+unsigned MCAsmStreamer::EmitCVFileDirective(unsigned FileNo,
+ StringRef Filename) {
+ if (!getContext().getCVFile(Filename, FileNo))
+ return 0;
+
+ OS << "\t.cv_file\t" << FileNo << ' ';
+
+ PrintQuotedString(Filename, OS);
+ EmitEOL();
+
+ return FileNo;
+}
+
+void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+ unsigned Line, unsigned Column,
+ bool PrologueEnd, bool IsStmt,
+ StringRef FileName) {
+ OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
+ << Column;
+ if (PrologueEnd)
+ OS << " prologue_end";
+
+ unsigned OldIsStmt = getContext().getCurrentCVLoc().isStmt();
+ if (IsStmt != OldIsStmt) {
+ OS << " is_stmt ";
+
+ if (IsStmt)
+ OS << "1";
+ else
+ OS << "0";
+ }
+
+ if (IsVerboseAsm) {
+ OS.PadToColumn(MAI->getCommentColumn());
+ OS << MAI->getCommentString() << ' ' << FileName << ':'
+ << Line << ':' << Column;
+ }
+ EmitEOL();
+ this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
+ PrologueEnd, IsStmt, FileName);
+}
+
+void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
+ const MCSymbol *FnStart,
+ const MCSymbol *FnEnd) {
+ OS << "\t.cv_linetable\t" << FunctionId << ", ";
+ FnStart->print(OS, MAI);
+ OS << ", ";
+ FnEnd->print(OS, MAI);
+ EmitEOL();
+ this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
+}
+
+void MCAsmStreamer::EmitCVInlineLinetableDirective(
+ unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
+ const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
+ ArrayRef<unsigned> SecondaryFunctionIds) {
+ OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
+ << ' ' << SourceLineNum << ' ';
+ FnStartSym->print(OS, MAI);
+ OS << ' ';
+ FnEndSym->print(OS, MAI);
+ if (!SecondaryFunctionIds.empty()) {
+ OS << " contains";
+ for (unsigned SecondaryFunctionId : SecondaryFunctionIds)
+ OS << ' ' << SecondaryFunctionId;
+ }
+ EmitEOL();
+ this->MCStreamer::EmitCVInlineLinetableDirective(
+ PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
+ SecondaryFunctionIds);
+}
+
+void MCAsmStreamer::EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ StringRef FixedSizePortion) {
+ OS << "\t.cv_def_range\t";
+ for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
+ OS << ' ';
+ Range.first->print(OS, MAI);
+ OS << ' ';
+ Range.second->print(OS, MAI);
+ }
+ OS << ", ";
+ PrintQuotedString(FixedSizePortion, OS);
+ EmitEOL();
+ this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
+}
+
+void MCAsmStreamer::EmitCVStringTableDirective() {
+ OS << "\t.cv_stringtable";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitCVFileChecksumsDirective() {
+ OS << "\t.cv_filechecksums";
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitIdent(StringRef IdentString) {
assert(MAI->hasIdentDirective() && ".ident directive not supported");
OS << "\t.ident\t";
@@ -1033,10 +1243,10 @@ void MCAsmStreamer::EmitCFIEscape(StringRef Values) {
void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) {
MCStreamer::EmitCFIGnuArgsSize(Size);
-
+
uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
-
+
PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
EmitEOL();
}
@@ -1178,8 +1388,8 @@ void MCAsmStreamer::EmitWinEHHandlerData() {
// We only do this so the section switch that terminates the handler
// data block is visible.
WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
- MCSection *XData =
- WinEH::UnwindEmitter::getXDataSection(CurFrame->Function, getContext());
+ MCSection *TextSec = &CurFrame->Function->getSection();
+ MCSection *XData = getAssociatedXDataSection(TextSec);
SwitchSectionNoChange(XData);
OS << "\t.seh_handlerdata";