void SVMELFProgramWriter::rwCompress(MCAssembler &Asm, const MCAsmLayout &Layout, SVMMemoryLayout &ML)
{
    /*
     * Look for all segments with initialized data for RAM, flatten them, and
     * compress the resulting data. Create a new segment with the compressed
     * RWDATA. This segment will always be included in the binary. The originals
     * are considered debug-only sections, since they are no longer needed
     * at runtime.
     */

    // Flattened binary contents of RAM
    std::vector<uint8_t> plaintext;

    // Iterate over SPS_RW sections
    for (MCAssembler::const_iterator IS = Asm.begin(), ES = Asm.end(); IS != ES; ++IS) {
        const MCSectionData *SD = &*IS;
        if (ML.getSectionKind(SD) != SPS_RW_PLAIN)
            continue;

        int offset = ML.getSectionMemAddress(SD) - SVMTargetMachine::getRAMBase();
        int limit = SVMTargetMachine::getRAMSize();

        // Iterate over fragments, pasting them into 'plaintext'
        for (MCSectionData::const_iterator IF = SD->begin(), EF = SD->end(); IF != EF; ++IF) {
            const MCFragment *F = &*IF;
            if (F->getKind() == MCFragment::FT_Data) {
                const MCDataFragment *DF = cast<MCDataFragment>(F);
                int fragmentOffset = Layout.getFragmentOffset(F);
                for (unsigned i = 0; i < DF->getContents().size(); i++) {
                    int totalOffset = fragmentOffset + offset + i;
                    if (totalOffset < limit) {
                        while (totalOffset >= int(plaintext.size()))
                            plaintext.push_back(0);
                        plaintext[totalOffset] = DF->getContents()[i];
                    }
                }
            }
        }
    }

    // FastLZ requires a minimum of 16 bytes to compress. Pad our section data.
    while (plaintext.size() < 16)
        plaintext.push_back(0);

    // Compress using FastLZ level 1
    std::vector<uint8_t> compressed(plaintext.size() * 2);
    compressed.resize(fastlz_compress_level(1, &plaintext[0], plaintext.size(), &compressed[0]));

    // Create the new section
    const MCSectionELF *LZSection =
        Asm.getContext().getELFSection(".rwdata.lz", ELF::SHT_NOTE,
                                       0, SectionKind::getDataNoRel());
    MCSectionData &LZSectionSD = Asm.getOrCreateSectionData(*LZSection);
    LZSectionSD.setAlignment(1);

    // Force it to be interpreted as SPS_RW, and set the decompressed size
    ML.setSectionKind(&LZSectionSD, SPS_RW_Z);
    ML.setSectionMemSize(&LZSectionSD, plaintext.size());

    // Add compressed data
    MCDataFragment *F = new MCDataFragment(&LZSectionSD);
    F->getContents().append(compressed.begin(), compressed.end());
}