From 8f9b80e5df12779a56d763ebf20864dad2bc72da Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 23 Mar 2010 02:36:58 +0000 Subject: [PATCH] MC: Add TargetAsmBackend::WriteNopData and use to eliminate some target dependencies in MCMachOStreamer and MCAssembler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99248 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetAsmBackend.h | 7 +++ lib/MC/MCAssembler.cpp | 71 ++++---------------------- lib/MC/MCMachOStreamer.cpp | 3 +- lib/Target/X86/X86AsmBackend.cpp | 63 +++++++++++++++++++++++ 4 files changed, 80 insertions(+), 64 deletions(-) diff --git a/include/llvm/Target/TargetAsmBackend.h b/include/llvm/Target/TargetAsmBackend.h index 1c553930183..16f33c32f48 100644 --- a/include/llvm/Target/TargetAsmBackend.h +++ b/include/llvm/Target/TargetAsmBackend.h @@ -102,6 +102,13 @@ public: /// wider instruction. virtual void RelaxInstruction(const MCInstFragment *IF, MCInst &Res) const = 0; + + /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given + /// output. If the target cannot generate such a sequence, it should return an + /// error. + /// + /// \return - True on success. + virtual bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const = 0; }; } // End llvm namespace diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 39bad6dea46..7672528524b 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -373,66 +373,9 @@ void MCAssembler::LayoutSection(MCSectionData &SD, SD.setFileSize(Address - SD.getAddress()); } -/// WriteNopData - Write optimal nops to the output file for the \arg Count -/// bytes. This returns the number of bytes written. It may return 0 if -/// the \arg Count is more than the maximum optimal nops. -/// -/// FIXME this is X86 32-bit specific and should move to a better place. -static uint64_t WriteNopData(uint64_t Count, MCObjectWriter *OW) { - static const uint8_t Nops[16][16] = { - // nop - {0x90}, - // xchg %ax,%ax - {0x66, 0x90}, - // nopl (%[re]ax) - {0x0f, 0x1f, 0x00}, - // nopl 0(%[re]ax) - {0x0f, 0x1f, 0x40, 0x00}, - // nopl 0(%[re]ax,%[re]ax,1) - {0x0f, 0x1f, 0x44, 0x00, 0x00}, - // nopw 0(%[re]ax,%[re]ax,1) - {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, - // nopl 0L(%[re]ax) - {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, - // nopl 0L(%[re]ax,%[re]ax,1) - {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, - // nopw 0L(%[re]ax,%[re]ax,1) - {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, - // nopw %cs:0L(%[re]ax,%[re]ax,1) - {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, - // nopl 0(%[re]ax,%[re]ax,1) - // nopw 0(%[re]ax,%[re]ax,1) - {0x0f, 0x1f, 0x44, 0x00, 0x00, - 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, - // nopw 0(%[re]ax,%[re]ax,1) - // nopw 0(%[re]ax,%[re]ax,1) - {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, - 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, - // nopw 0(%[re]ax,%[re]ax,1) - // nopl 0L(%[re]ax) */ - {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, - 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, - // nopl 0L(%[re]ax) - // nopl 0L(%[re]ax) - {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, - // nopl 0L(%[re]ax) - // nopl 0L(%[re]ax,%[re]ax,1) - {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00} - }; - - if (Count > 15) - return 0; - - for (uint64_t i = 0; i < Count; i++) - OW->Write8(uint8_t(Nops[Count - 1][i])); - - return Count; -} - /// WriteFragmentData - Write the \arg F data to the output file. -static void WriteFragmentData(const MCFragment &F, MCObjectWriter *OW) { +static void WriteFragmentData(const MCAssembler &Asm, const MCFragment &F, + MCObjectWriter *OW) { uint64_t Start = OW->getStream().tell(); (void) Start; @@ -456,11 +399,15 @@ static void WriteFragmentData(const MCFragment &F, MCObjectWriter *OW) { // See if we are aligning with nops, and if so do that first to try to fill // the Count bytes. Then if that did not fill any bytes or there are any // bytes left to fill use the the Value and ValueSize to fill the rest. + // If we are aligning with nops, ask that target to emit the right data. if (AF.getEmitNops()) { - uint64_t NopByteCount = WriteNopData(Count, OW); - Count -= NopByteCount; + if (!Asm.getBackend().WriteNopData(Count, OW)) + llvm_report_error("unable to write nop sequence of " + + Twine(Count) + " bytes"); + break; } + // Otherwise, write out in multiples of the value size. for (uint64_t i = 0; i != Count; ++i) { switch (AF.getValueSize()) { default: @@ -531,7 +478,7 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD, for (MCSectionData::const_iterator it = SD->begin(), ie = SD->end(); it != ie; ++it) - WriteFragmentData(*it, OW); + WriteFragmentData(*this, *it, OW); // Add section padding. assert(SD->getFileSize() >= SD->getSize() && "Invalid section sizes!"); diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 51a2d45ed71..a52d962c9a4 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -353,8 +353,7 @@ void MCMachOStreamer::EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit) { if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; - // FIXME: The 0x90 is the default x86 1 byte nop opcode. - new MCAlignFragment(ByteAlignment, 0x90, 1, MaxBytesToEmit, + new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, true /* EmitNops */, CurSectionData); // Update the maximum alignment on the current section if necessary. diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp index e918cb0a923..3e4e2b5ae2f 100644 --- a/lib/Target/X86/X86AsmBackend.cpp +++ b/lib/Target/X86/X86AsmBackend.cpp @@ -53,6 +53,8 @@ public: } void RelaxInstruction(const MCInstFragment *IF, MCInst &Res) const; + + bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const; }; static unsigned getRelaxedOpcode(unsigned Op) { @@ -98,6 +100,67 @@ void X86AsmBackend::RelaxInstruction(const MCInstFragment *IF, Res.setOpcode(RelaxedOp); } +/// WriteNopData - Write optimal nops to the output file for the \arg Count +/// bytes. This returns the number of bytes written. It may return 0 if +/// the \arg Count is more than the maximum optimal nops. +/// +/// FIXME this is X86 32-bit specific and should move to a better place. +bool X86AsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { + static const uint8_t Nops[16][16] = { + // nop + {0x90}, + // xchg %ax,%ax + {0x66, 0x90}, + // nopl (%[re]ax) + {0x0f, 0x1f, 0x00}, + // nopl 0(%[re]ax) + {0x0f, 0x1f, 0x40, 0x00}, + // nopl 0(%[re]ax,%[re]ax,1) + {0x0f, 0x1f, 0x44, 0x00, 0x00}, + // nopw 0(%[re]ax,%[re]ax,1) + {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, + // nopl 0L(%[re]ax) + {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, + // nopl 0L(%[re]ax,%[re]ax,1) + {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + // nopw 0L(%[re]ax,%[re]ax,1) + {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + // nopw %cs:0L(%[re]ax,%[re]ax,1) + {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + // nopl 0(%[re]ax,%[re]ax,1) + // nopw 0(%[re]ax,%[re]ax,1) + {0x0f, 0x1f, 0x44, 0x00, 0x00, + 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, + // nopw 0(%[re]ax,%[re]ax,1) + // nopw 0(%[re]ax,%[re]ax,1) + {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, + 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, + // nopw 0(%[re]ax,%[re]ax,1) + // nopl 0L(%[re]ax) */ + {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, + 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, + // nopl 0L(%[re]ax) + // nopl 0L(%[re]ax) + {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, + // nopl 0L(%[re]ax) + // nopl 0L(%[re]ax,%[re]ax,1) + {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00} + }; + + // Write an optimal sequence for the first 15 bytes. + uint64_t OptimalCount = (Count < 16) ? Count : 15; + for (uint64_t i = 0, e = OptimalCount; i != e; i++) + OW->Write8(Nops[OptimalCount - 1][i]); + + // Finish with single byte nops. + for (uint64_t i = OptimalCount, e = Count; i != e; ++i) + OW->Write8(0x90); + + return true; +} + /* *** */ class ELFX86AsmBackend : public X86AsmBackend { -- 2.34.1