diff options
| -rw-r--r-- | llvm/include/llvm/MC/MCAssembler.h | 10 | ||||
| -rw-r--r-- | llvm/include/llvm/MC/MCStreamer.h | 14 | ||||
| -rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 23 | ||||
| -rw-r--r-- | llvm/lib/MC/MCMachOStreamer.cpp | 17 | ||||
| -rw-r--r-- | llvm/lib/MC/MCNullStreamer.cpp | 3 | 
6 files changed, 73 insertions, 3 deletions
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 4527f3c28d3..882929f2eee 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -195,12 +195,16 @@ class MCAlignFragment : public MCFragment {    /// cannot be satisfied in this width then this fragment is ignored.    unsigned MaxBytesToEmit; +  /// EmitNops - true when aligning code and optimal nops to be used for filling +  bool EmitNops; +  public:    MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, -                  unsigned _MaxBytesToEmit, MCSectionData *SD = 0) +                  unsigned _MaxBytesToEmit, bool _EmitNops, +		  MCSectionData *SD = 0)      : MCFragment(FT_Align, SD), Alignment(_Alignment),        Value(_Value),ValueSize(_ValueSize), -      MaxBytesToEmit(_MaxBytesToEmit) {} +      MaxBytesToEmit(_MaxBytesToEmit), EmitNops(_EmitNops) {}    /// @name Accessors    /// @{ @@ -217,6 +221,8 @@ public:    unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } +  unsigned getEmitNops() const { return EmitNops; } +    /// @}    static bool classof(const MCFragment *F) { diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index b104b9ad570..696d024aa85 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -232,6 +232,20 @@ namespace llvm {                                        unsigned ValueSize = 1,                                        unsigned MaxBytesToEmit = 0) = 0; +    /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment +    /// is reached. +    /// +    /// This used to align code where the alignment bytes may be executed.  This +    /// can emit different bytes for different sizes to optimize execution. +    /// +    /// @param ByteAlignment - The alignment to reach. This must be a power of +    /// two on some targets. +    /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If +    /// the alignment cannot be reached in this many bytes, no bytes are +    /// emitted. +    virtual void EmitCodeAlignment(unsigned ByteAlignment, +                                   unsigned MaxBytesToEmit = 0) = 0; +      /// EmitValueToOffset - Emit some number of copies of @p Value until the      /// byte offset @p Offset is reached.      /// diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 6add1b4abaa..07a9553ff1d 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -134,6 +134,9 @@ public:                                      unsigned ValueSize = 1,                                      unsigned MaxBytesToEmit = 0); +  virtual void EmitCodeAlignment(unsigned ByteAlignment, +                                 unsigned MaxBytesToEmit = 0); +    virtual void EmitValueToOffset(const MCExpr *Offset,                                   unsigned char Value = 0); @@ -513,6 +516,12 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,    EmitEOL();  } +void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, +                                      unsigned MaxBytesToEmit) { +  // FIXME: a hack for now to only work for x86 using the 0x90 nop opcode. +  EmitValueToAlignment(ByteAlignment, 0x90, 1, MaxBytesToEmit); +} +  void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset,                                        unsigned char Value) {    // FIXME: Verify that Offset is associated with the current section. diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 528c5c025d5..2c698e76f92 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -42,6 +42,8 @@ STATISTIC(EmittedFragments, "Number of emitted assembler fragments");  static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,                            MachObjectWriter &MOW); +static uint64_t WriteNopData(uint64_t Count, MachObjectWriter &MOW); +  /// isVirtualSection - Check if this is a section which does not actually exist  /// in the object file.  static bool isVirtualSection(const MCSection &Section) { @@ -1058,6 +1060,19 @@ 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, MachObjectWriter &MOW) { +  // FIXME for now just use the 0x90 nop opcode byte. +  for (uint64_t i = 0; i < Count; i++) +    MOW.Write8 (uint8_t(0x90)); + +  return Count; +} +  /// WriteFileData - Write the \arg F data to the output file.  static void WriteFileData(raw_ostream &OS, const MCFragment &F,                            MachObjectWriter &MOW) { @@ -1081,6 +1096,14 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,                          "' is not a divisor of padding size '" +                          Twine(AF.getFileSize()) + "'"); +    // 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 (AF.getEmitNops()) { +      uint64_t NopByteCount = WriteNopData(Count, MOW); +      Count -= NopByteCount; +    } +      for (uint64_t i = 0; i != Count; ++i) {        switch (AF.getValueSize()) {        default: diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index 797be86caf2..a7a8a5daed9 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -137,6 +137,8 @@ public:    virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,                                      unsigned ValueSize = 1,                                      unsigned MaxBytesToEmit = 0); +  virtual void EmitCodeAlignment(unsigned ByteAlignment, +                                 unsigned MaxBytesToEmit = 0);    virtual void EmitValueToOffset(const MCExpr *Offset,                                   unsigned char Value = 0); @@ -357,7 +359,20 @@ void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment,    if (MaxBytesToEmit == 0)      MaxBytesToEmit = ByteAlignment;    new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, -                      CurSectionData); +                      false /* EmitNops */, CurSectionData); + +  // Update the maximum alignment on the current section if necessary. +  if (ByteAlignment > CurSectionData->getAlignment()) +    CurSectionData->setAlignment(ByteAlignment); +} + +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, +                      true /* EmitNops */, CurSectionData);    // Update the maximum alignment on the current section if necessary.    if (ByteAlignment > CurSectionData->getAlignment()) diff --git a/llvm/lib/MC/MCNullStreamer.cpp b/llvm/lib/MC/MCNullStreamer.cpp index 46e9ebfa886..ab6179907e8 100644 --- a/llvm/lib/MC/MCNullStreamer.cpp +++ b/llvm/lib/MC/MCNullStreamer.cpp @@ -55,6 +55,9 @@ namespace {                                        unsigned ValueSize = 1,                                        unsigned MaxBytesToEmit = 0) {} +    virtual void EmitCodeAlignment(unsigned ByteAlignment, +                                   unsigned MaxBytesToEmit = 0) {} +      virtual void EmitValueToOffset(const MCExpr *Offset,                                     unsigned char Value = 0) {}  | 

