diff options
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 910295c5d2b..fcf1b50a4f7 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -28,6 +28,9 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/Host.h" using namespace llvm; @@ -230,6 +233,39 @@ MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() { /* *** */ +const SmallVectorImpl<char> &MCCompressedFragment::getCompressedContents() const { + assert(getParent()->size() == 1 && + "Only compress sections containing a single fragment"); + if (CompressedContents.empty()) { + std::unique_ptr<MemoryBuffer> CompressedSection; + zlib::Status Success = + zlib::compress(StringRef(getContents().data(), getContents().size()), + CompressedSection); + (void)Success; + assert(Success == zlib::StatusOK); + CompressedContents.push_back('Z'); + CompressedContents.push_back('L'); + CompressedContents.push_back('I'); + CompressedContents.push_back('B'); + uint64_t Size = getContents().size(); + if (sys::IsLittleEndianHost) + Size = sys::SwapByteOrder(Size); + CompressedContents.append(reinterpret_cast<char *>(&Size), + reinterpret_cast<char *>(&Size + 1)); + CompressedContents.append(CompressedSection->getBuffer().begin(), + CompressedSection->getBuffer().end()); + } + return CompressedContents; +} + +SmallVectorImpl<char> &MCCompressedFragment::getContents() { + assert(CompressedContents.empty() && + "Fragment contents should not be altered after compression"); + return MCDataFragment::getContents(); +} + +/* *** */ + MCSectionData::MCSectionData() : Section(0) {} MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) @@ -430,6 +466,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, case MCFragment::FT_Relaxable: case MCFragment::FT_CompactEncodedInst: return cast<MCEncodedFragment>(F).getContents().size(); + case MCFragment::FT_Compressed: + return cast<MCCompressedFragment>(F).getCompressedContents().size(); case MCFragment::FT_Fill: return cast<MCFillFragment>(F).getSize(); @@ -618,6 +656,11 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, break; } + case MCFragment::FT_Compressed: + ++stats::EmittedDataFragments; + OW->WriteBytes(cast<MCCompressedFragment>(F).getCompressedContents()); + break; + case MCFragment::FT_Data: ++stats::EmittedDataFragments; writeFragmentContents(F, OW); @@ -694,6 +737,7 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, ie = SD->end(); it != ie; ++it) { switch (it->getKind()) { default: llvm_unreachable("Invalid fragment in virtual section!"); + case MCFragment::FT_Compressed: case MCFragment::FT_Data: { // Check that we aren't trying to write a non-zero contents (or fixups) // into a virtual section. This is to support clients which use standard @@ -1021,6 +1065,8 @@ void MCFragment::dump() { switch (getKind()) { case MCFragment::FT_Align: OS << "MCAlignFragment"; break; case MCFragment::FT_Data: OS << "MCDataFragment"; break; + case MCFragment::FT_Compressed: + OS << "MCCompressedFragment"; break; case MCFragment::FT_CompactEncodedInst: OS << "MCCompactEncodedInstFragment"; break; case MCFragment::FT_Fill: OS << "MCFillFragment"; break; @@ -1047,6 +1093,7 @@ void MCFragment::dump() { << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">"; break; } + case MCFragment::FT_Compressed: case MCFragment::FT_Data: { const MCDataFragment *DF = cast<MCDataFragment>(this); OS << "\n "; |