summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCAssembler.h23
-rw-r--r--lib/MC/MCAsmInfo.cpp2
-rw-r--r--lib/MC/MCAssembler.cpp47
-rw-r--r--lib/MC/MCContext.cpp19
-rw-r--r--lib/MC/MCObjectStreamer.cpp7
-rw-r--r--test/MC/ELF/compression.s18
-rw-r--r--tools/llvm-mc/llvm-mc.cpp6
7 files changed, 112 insertions, 10 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 4b519dd7c9..506e555e48 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -51,6 +51,7 @@ public:
enum FragmentType {
FT_Align,
FT_Data,
+ FT_Compressed,
FT_CompactEncodedInst,
FT_Fill,
FT_Relaxable,
@@ -160,6 +161,7 @@ public:
return false;
case MCFragment::FT_Relaxable:
case MCFragment::FT_CompactEncodedInst:
+ case MCFragment::FT_Compressed:
case MCFragment::FT_Data:
return true;
}
@@ -194,7 +196,8 @@ public:
static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind();
- return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data;
+ return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
+ Kind == MCFragment::FT_Compressed;
}
};
@@ -213,6 +216,11 @@ class MCDataFragment : public MCEncodedFragmentWithFixups {
/// Fixups - The list of fixups in this fragment.
SmallVector<MCFixup, 4> Fixups;
+protected:
+ MCDataFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0)
+ : MCEncodedFragmentWithFixups(FType, SD), HasInstructions(false),
+ AlignToBundleEnd(false) {}
+
public:
MCDataFragment(MCSectionData *SD = 0)
: MCEncodedFragmentWithFixups(FT_Data, SD),
@@ -246,10 +254,21 @@ public:
const_fixup_iterator fixup_end() const override {return Fixups.end();}
static bool classof(const MCFragment *F) {
- return F->getKind() == MCFragment::FT_Data;
+ return F->getKind() == MCFragment::FT_Data ||
+ F->getKind() == MCFragment::FT_Compressed;
}
};
+class MCCompressedFragment: public MCDataFragment {
+ mutable SmallVector<char, 32> CompressedContents;
+public:
+ MCCompressedFragment(MCSectionData *SD = nullptr)
+ : MCDataFragment(FT_Compressed, SD) {}
+ const SmallVectorImpl<char> &getCompressedContents() const;
+ using MCDataFragment::getContents;
+ SmallVectorImpl<char> &getContents() override;
+};
+
/// This is a compact (memory-size-wise) fragment for holding an encoded
/// instruction (non-relaxable) that has no fixups registered. When applicable,
/// it can be used instead of MCDataFragment and lead to lower memory
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index f09bbd1a66..c78d3d574a 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -100,6 +100,8 @@ MCAsmInfo::MCAsmInfo() {
// architecture basis.
// - The target subclasses for AArch64, ARM, and X86 handle these cases
UseIntegratedAssembler = false;
+
+ CompressDebugSections = false;
}
MCAsmInfo::~MCAsmInfo() {
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 910295c5d2..fcf1b50a4f 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/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 ";
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index ede3b3cd23..b228d18ba7 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -37,13 +37,13 @@ typedef std::map<SectionGroupPair, const MCSectionCOFF *> COFFUniqueMapTy;
MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
const MCObjectFileInfo *mofi, const SourceMgr *mgr,
- bool DoAutoReset) :
- SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi),
- Allocator(), Symbols(Allocator), UsedNames(Allocator),
- NextUniqueID(0),
- CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0),
- DwarfLocSeen(false), GenDwarfForAssembly(false), GenDwarfFileNumber(0),
- AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset) {
+ bool DoAutoReset)
+ : SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi), Allocator(),
+ Symbols(Allocator), UsedNames(Allocator), NextUniqueID(0),
+ CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), DwarfLocSeen(false),
+ GenDwarfForAssembly(false), GenDwarfFileNumber(0),
+ AllowTemporaryLabels(true), DwarfCompileUnitID(0),
+ AutoReset(DoAutoReset) {
error_code EC = llvm::sys::fs::current_path(CompilationDir);
if (EC)
@@ -251,6 +251,11 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags,
ELFUniquingMap = new ELFUniqueMapTy();
ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap;
+ SmallString<32> ZDebugName;
+ if (MAI->compressDebugSections() && Section.startswith(".debug_") &&
+ Section != ".debug_frame")
+ Section = (".z" + Section.drop_front(1)).toStringRef(ZDebugName);
+
// Do the lookup, if we have a hit, return it.
std::pair<ELFUniqueMapTy::iterator, bool> Entry = Map.insert(
std::make_pair(SectionGroupPair(Section, Group), (MCSectionELF *)0));
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 809cb11e36..35786accb4 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -20,6 +20,7 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/MC/MCSectionELF.h"
using namespace llvm;
MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB,
@@ -63,7 +64,11 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const {
// When bundling is enabled, we don't want to add data to a fragment that
// already has instructions (see MCELFStreamer::EmitInstToData for details)
if (!F || (Assembler->isBundlingEnabled() && F->hasInstructions())) {
- F = new MCDataFragment();
+ const auto *Sec = dyn_cast<MCSectionELF>(&getCurrentSectionData()->getSection());
+ if (Sec && Sec->getSectionName().startswith(".zdebug_"))
+ F = new MCCompressedFragment();
+ else
+ F = new MCDataFragment();
insert(F);
}
return F;
diff --git a/test/MC/ELF/compression.s b/test/MC/ELF/compression.s
new file mode 100644
index 0000000000..0293a3c9c5
--- /dev/null
+++ b/test/MC/ELF/compression.s
@@ -0,0 +1,18 @@
+// RUN: llvm-mc -filetype=obj -compress-debug-sections -triple x86_64-pc-linux-gnu %s -o - | llvm-objdump -s - | FileCheck %s
+
+// CHECK: Contents of section .zdebug_line:
+// Check for the 'ZLIB' file magic at the start of the section
+// CHECK-NEXT: ZLIB
+// We shouldn't compress the debug_frame section, since it can be relaxed
+// CHECK: Contents of section .debug_frame
+// CHECK-NOT: ZLIB
+
+ .section .debug_line,"",@progbits
+ .text
+foo:
+ .cfi_startproc
+ .file 1 "Driver.ii"
+ .loc 1 2 0
+ nop
+ .cfi_endproc
+ .cfi_sections .debug_frame
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index a4b4a844f6..b2e7a81488 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -50,6 +50,9 @@ static cl::opt<bool>
ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
static cl::opt<bool>
+CompressDebugSections("compress-debug-sections", cl::desc("Compress DWARF debug sections"));
+
+static cl::opt<bool>
ShowInst("show-inst", cl::desc("Show internal instruction representation"));
static cl::opt<bool>
@@ -381,6 +384,9 @@ int main(int argc, char **argv) {
std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
assert(MAI && "Unable to create target asm info!");
+ if (CompressDebugSections)
+ MAI->setCompressDebugSections(true);
+
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());