summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r--llvm/lib/MC/MCAssembler.cpp47
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 ";
OpenPOWER on IntegriCloud