[llvm-commits] [llvm] r170718 - in /llvm/trunk: include/llvm/MC/MCAsmLayout.h include/llvm/MC/MCAssembler.h include/llvm/MC/MCELFStreamer.h include/llvm/MC/MCObjectStreamer.h include/llvm/MC/MCStreamer.h lib/MC/MCAsmStreamer.cpp lib/MC/MCAssembler.cpp lib/MC/MCELFStreamer.cpp lib/MC/MCNullStreamer.cpp lib/MC/MCObjectStreamer.cpp lib/MC/MCParser/AsmParser.cpp tools/lto/LTOModule.cpp

Matt Beaumont-Gay matthewbg at google.com
Thu Dec 20 13:46:37 PST 2012


Hi Eli,

Our internal buildbot with a freshly built Clang is reporting a number
of "fatal error: error in backend: Fragment can't be larger than a
bundle size" errors on various inputs, including a file in ICU. I
don't have a small test case yet, but I wanted to give you a heads-up.

On Thu, Dec 20, 2012 at 11:05 AM, Eli Bendersky <eliben at google.com> wrote:
> Author: eliben
> Date: Thu Dec 20 13:05:53 2012
> New Revision: 170718
>
> URL: http://llvm.org/viewvc/llvm-project?rev=170718&view=rev
> Log:
> Aligned bundling support. Following the discussion here:
> http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-December/056754.html
>
> The proposal and implementation are fully documented here:
> https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/aligned-bundling-support-in-llvm
>
> Tests will follow shortly.
>
> Modified:
>     llvm/trunk/include/llvm/MC/MCAsmLayout.h
>     llvm/trunk/include/llvm/MC/MCAssembler.h
>     llvm/trunk/include/llvm/MC/MCELFStreamer.h
>     llvm/trunk/include/llvm/MC/MCObjectStreamer.h
>     llvm/trunk/include/llvm/MC/MCStreamer.h
>     llvm/trunk/lib/MC/MCAsmStreamer.cpp
>     llvm/trunk/lib/MC/MCAssembler.cpp
>     llvm/trunk/lib/MC/MCELFStreamer.cpp
>     llvm/trunk/lib/MC/MCNullStreamer.cpp
>     llvm/trunk/lib/MC/MCObjectStreamer.cpp
>     llvm/trunk/lib/MC/MCParser/AsmParser.cpp
>     llvm/trunk/tools/lto/LTOModule.cpp
>
> Modified: llvm/trunk/include/llvm/MC/MCAsmLayout.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAsmLayout.h?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCAsmLayout.h (original)
> +++ llvm/trunk/include/llvm/MC/MCAsmLayout.h Thu Dec 20 13:05:53 2012
> @@ -49,6 +49,11 @@
>    /// \brief Is the layout for this fragment valid?
>    bool isFragmentValid(const MCFragment *F) const;
>
> +  /// \brief Compute the amount of padding required before this fragment to
> +  /// obey bundling restrictions.
> +  uint64_t computeBundlePadding(const MCFragment *F,
> +                                uint64_t FOffset, uint64_t FSize);
> +
>  public:
>    MCAsmLayout(MCAssembler &_Assembler);
>
>
> Modified: llvm/trunk/include/llvm/MC/MCAssembler.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAssembler.h?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCAssembler.h (original)
> +++ llvm/trunk/include/llvm/MC/MCAssembler.h Thu Dec 20 13:05:53 2012
> @@ -99,14 +99,35 @@
>    unsigned getLayoutOrder() const { return LayoutOrder; }
>    void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
>
> +  /// \brief Does this fragment have instructions emitted into it? By default
> +  ///  this is false, but specific fragment types may set it to true.
> +  virtual bool hasInstructions() const { return false; }
> +
> +  /// \brief Get the padding size that must be inserted before this fragment.
> +  /// Used for bundling. By default, no padding is inserted.
> +  /// Note that padding size is restricted to 8 bits. This is an optimization
> +  /// to reduce the amount of space used for each fragment. In practice, larger
> +  /// padding should never be required.
> +  virtual uint8_t getBundlePadding() const {
> +    return 0;
> +  }
> +
> +  /// \brief Set the padding size for this fragment. By default it's a no-op,
> +  /// and only some fragments have a meaningful implementation.
> +  virtual void setBundlePadding(uint8_t N) {
> +  }
> +
>    void dump();
>  };
>
>  class MCEncodedFragment : public MCFragment {
>    virtual void anchor();
> +
> +  uint8_t BundlePadding;
>  public:
>    MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0)
> -    : MCFragment(FType, SD) {
> +    : MCFragment(FType, SD), BundlePadding(0)
> +  {
>    }
>    virtual ~MCEncodedFragment();
>
> @@ -124,6 +145,14 @@
>    virtual fixup_iterator fixup_end() = 0;
>    virtual const_fixup_iterator fixup_end() const = 0;
>
> +  virtual uint8_t getBundlePadding() const {
> +    return BundlePadding;
> +  }
> +
> +  virtual void setBundlePadding(uint8_t N) {
> +    BundlePadding = N;
> +  }
> +
>    static bool classof(const MCFragment *F) {
>      MCFragment::FragmentType Kind = F->getKind();
>      return Kind == MCFragment::FT_Inst || Kind == MCFragment::FT_Data;
> @@ -132,14 +161,19 @@
>
>  class MCDataFragment : public MCEncodedFragment {
>    virtual void anchor();
> +
> +  /// \brief Does this fragment contain encoded instructions anywhere in it?
> +  bool HasInstructions;
> +
>    SmallVector<char, 32> Contents;
>
>    /// Fixups - The list of fixups in this fragment.
>    SmallVector<MCFixup, 4> Fixups;
> -
>  public:
>    MCDataFragment(MCSectionData *SD = 0)
> -    : MCEncodedFragment(FT_Data, SD) {
> +    : MCEncodedFragment(FT_Data, SD),
> +      HasInstructions(false)
> +  {
>    }
>
>    virtual SmallVectorImpl<char> &getContents() { return Contents; }
> @@ -153,6 +187,9 @@
>      return Fixups;
>    }
>
> +  virtual bool hasInstructions() const { return HasInstructions; }
> +  virtual void setHasInstructions(bool V) { HasInstructions = V; }
> +
>    fixup_iterator fixup_begin() { return Fixups.begin(); }
>    const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
>
> @@ -196,6 +233,8 @@
>      return Fixups;
>    }
>
> +  virtual bool hasInstructions() const { return true; }
> +
>    fixup_iterator fixup_begin() { return Fixups.begin(); }
>    const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
>
> @@ -450,6 +489,13 @@
>    /// Alignment - The maximum alignment seen in this section.
>    unsigned Alignment;
>
> +  /// \brief We're currently inside a bundle-locked group.
> +  bool BundleLocked;
> +
> +  /// \brief We've seen a bundle_lock directive but not its first instruction
> +  /// yet.
> +  bool BundleGroupBeforeFirstInst;
> +
>    /// @name Assembler Backend Data
>    /// @{
>    //
> @@ -502,6 +548,22 @@
>
>    bool empty() const { return Fragments.empty(); }
>
> +  bool isBundleLocked() const {
> +    return BundleLocked;
> +  }
> +
> +  void setBundleLocked(bool IsLocked) {
> +    BundleLocked = IsLocked;
> +  }
> +
> +  bool isBundleGroupBeforeFirstInst() const {
> +    return BundleGroupBeforeFirstInst;
> +  }
> +
> +  void setBundleGroupBeforeFirstInst(bool IsFirst) {
> +    BundleGroupBeforeFirstInst = IsFirst;
> +  }
> +
>    void dump();
>
>    /// @}
> @@ -707,6 +769,11 @@
>    // refactoring too.
>    SmallPtrSet<const MCSymbol*, 64> ThumbFuncs;
>
> +  /// \brief The bundle alignment size currently set in the assembler.
> +  ///
> +  /// By default it's 0, which means bundling is disabled.
> +  unsigned BundleAlignSize;
> +
>    unsigned RelaxAll : 1;
>    unsigned NoExecStack : 1;
>    unsigned SubsectionsViaSymbols : 1;
> @@ -833,6 +900,20 @@
>    bool getNoExecStack() const { return NoExecStack; }
>    void setNoExecStack(bool Value) { NoExecStack = Value; }
>
> +  bool isBundlingEnabled() const {
> +    return BundleAlignSize != 0;
> +  }
> +
> +  unsigned getBundleAlignSize() const {
> +    return BundleAlignSize;
> +  }
> +
> +  void setBundleAlignSize(unsigned Size) {
> +    assert((Size == 0 || !(Size & (Size - 1))) &&
> +           "Expect a power-of-two bundle align size");
> +    BundleAlignSize = Size;
> +  }
> +
>    /// @name Section List Access
>    /// @{
>
>
> Modified: llvm/trunk/include/llvm/MC/MCELFStreamer.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCELFStreamer.h?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCELFStreamer.h (original)
> +++ llvm/trunk/include/llvm/MC/MCELFStreamer.h Thu Dec 20 13:05:53 2012
> @@ -76,6 +76,8 @@
>
>    virtual void EmitTCEntry(const MCSymbol &S);
>
> +  virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned);
> +
>    virtual void FinishImpl();
>    /// @}
>
> @@ -83,6 +85,10 @@
>    virtual void EmitInstToFragment(const MCInst &Inst);
>    virtual void EmitInstToData(const MCInst &Inst);
>
> +  virtual void EmitBundleAlignMode(unsigned AlignPow2);
> +  virtual void EmitBundleLock();
> +  virtual void EmitBundleUnlock();
> +
>    void fixSymbolsInTLSFixups(const MCExpr *expr);
>
>    struct LocalCommon {
>
> Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
> +++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Thu Dec 20 13:05:53 2012
> @@ -78,7 +78,14 @@
>    virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
>    virtual void ChangeSection(const MCSection *Section);
>    virtual void EmitInstruction(const MCInst &Inst);
> +
> +  /// \brief Emit an instruction to a special fragment, because this instruction
> +  /// can change its size during relaxation.
>    virtual void EmitInstToFragment(const MCInst &Inst);
> +
> +  virtual void EmitBundleAlignMode(unsigned AlignPow2);
> +  virtual void EmitBundleLock();
> +  virtual void EmitBundleUnlock();
>    virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
>    virtual void EmitValueToAlignment(unsigned ByteAlignment,
>                                      int64_t Value = 0,
>
> Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
> +++ llvm/trunk/include/llvm/MC/MCStreamer.h Thu Dec 20 13:05:53 2012
> @@ -437,7 +437,6 @@
>        EmitFill(NumBytes, 0, AddrSpace);
>      }
>
> -
>      /// EmitValueToAlignment - Emit some number of copies of @p Value until
>      /// the byte alignment @p ByteAlignment is reached.
>      ///
> @@ -557,6 +556,17 @@
>      /// section.
>      virtual void EmitInstruction(const MCInst &Inst) = 0;
>
> +    /// \brief Set the bundle alignment mode from now on in the section.
> +    /// The argument is the power of 2 to which the alignment is set. The
> +    /// value 0 means turn the bundle alignment off.
> +    virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0;
> +
> +    /// \brief The following instructions are a bundle-locked group.
> +    virtual void EmitBundleLock() = 0;
> +
> +    /// \brief Ends a bundle-locked group.
> +    virtual void EmitBundleUnlock() = 0;
> +
>      /// EmitRawText - If this file is backed by a assembly streamer, this dumps
>      /// the specified string in the output .s file.  This capability is
>      /// indicated by the hasRawTextSupport() predicate.  By default this aborts.
>
> Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
> +++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Thu Dec 20 13:05:53 2012
> @@ -259,6 +259,10 @@
>
>    virtual void EmitInstruction(const MCInst &Inst);
>
> +  virtual void EmitBundleAlignMode(unsigned AlignPow2);
> +  virtual void EmitBundleLock();
> +  virtual void EmitBundleUnlock();
> +
>    /// EmitRawText - If this file is backed by an assembly streamer, this dumps
>    /// the specified string in the output .s file.  This capability is
>    /// indicated by the hasRawTextSupport() predicate.
> @@ -1361,6 +1365,21 @@
>    EmitEOL();
>  }
>
> +void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
> +  OS << "\t.bundle_align_mode " << AlignPow2;
> +  EmitEOL();
> +}
> +
> +void MCAsmStreamer::EmitBundleLock() {
> +  OS << "\t.bundle_lock";
> +  EmitEOL();
> +}
> +
> +void MCAsmStreamer::EmitBundleUnlock() {
> +  OS << "\t.bundle_unlock";
> +  EmitEOL();
> +}
> +
>  /// EmitRawText - If this file is backed by an assembly streamer, this dumps
>  /// the specified string in the output .s file.  This capability is
>  /// indicated by the hasRawTextSupport() predicate.
>
> Modified: llvm/trunk/lib/MC/MCAssembler.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/lib/MC/MCAssembler.cpp (original)
> +++ llvm/trunk/lib/MC/MCAssembler.cpp Thu Dec 20 13:05:53 2012
> @@ -160,6 +160,22 @@
>    return getSectionAddressSize(SD);
>  }
>
> +uint64_t MCAsmLayout::computeBundlePadding(const MCFragment *F,
> +                                           uint64_t FOffset, uint64_t FSize) {
> +  uint64_t BundleSize = Assembler.getBundleAlignSize();
> +  assert(BundleSize > 0 &&
> +         "computeBundlePadding should only be called if bundling is enabled");
> +  uint64_t BundleMask = BundleSize - 1;
> +  uint64_t OffsetInBundle = FOffset & BundleMask;
> +
> +  // If the fragment would cross a bundle boundary, add enough padding until
> +  // the end of the current bundle.
> +  if (OffsetInBundle + FSize > BundleSize)
> +    return BundleSize - OffsetInBundle;
> +  else
> +    return 0;
> +}
> +
>  /* *** */
>
>  MCFragment::MCFragment() : Kind(FragmentType(~0)) {
> @@ -188,6 +204,7 @@
>    : Section(&_Section),
>      Ordinal(~UINT32_C(0)),
>      Alignment(1),
> +    BundleLocked(false), BundleGroupBeforeFirstInst(false),
>      HasInstructions(false)
>  {
>    if (A)
> @@ -406,12 +423,42 @@
>    ++stats::FragmentLayouts;
>
>    // Compute fragment offset and size.
> -  uint64_t Offset = 0;
>    if (Prev)
> -    Offset += Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev);
> -
> -  F->Offset = Offset;
> +    F->Offset = Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev);
> +  else
> +    F->Offset = 0;
>    LastValidFragment[F->getParent()] = F;
> +
> +  // If bundling is enabled and this fragment has instructions in it, it has to
> +  // obey the bundling restrictions. With padding, we'll have:
> +  //
> +  //
> +  //        BundlePadding
> +  //             |||
> +  // -------------------------------------
> +  //   Prev  |##########|       F        |
> +  // -------------------------------------
> +  //                    ^
> +  //                    |
> +  //                    F->Offset
> +  //
> +  // The fragment's offset will point to after the padding, and its computed
> +  // size won't include the padding.
> +  //
> +  if (Assembler.isBundlingEnabled() && F->hasInstructions()) {
> +    assert(isa<MCEncodedFragment>(F) &&
> +           "Only MCEncodedFragment implementations have instructions");
> +    uint64_t FSize = Assembler.computeFragmentSize(*this, *F);
> +
> +    if (FSize > Assembler.getBundleAlignSize())
> +      report_fatal_error("Fragment can't be larger than a bundle size");
> +
> +    uint64_t RequiredBundlePadding = computeBundlePadding(F, F->Offset, FSize);
> +    if (RequiredBundlePadding > UINT8_MAX)
> +      report_fatal_error("Padding cannot exceed 255 bytes");
> +    F->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
> +    F->Offset += RequiredBundlePadding;
> +  }
>  }
>
>  /// \brief Write the contents of a fragment to the given object writer. Expects
> @@ -425,6 +472,22 @@
>  static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
>                            const MCFragment &F) {
>    MCObjectWriter *OW = &Asm.getWriter();
> +
> +  // Should NOP padding be written out before this fragment?
> +  unsigned BundlePadding = F.getBundlePadding();
> +  if (BundlePadding > 0) {
> +    assert(Asm.isBundlingEnabled() &&
> +           "Writing bundle padding with disabled bundling");
> +    assert(F.hasInstructions() &&
> +           "Writing bundle padding for a fragment without instructions");
> +
> +    if (!Asm.getBackend().writeNopData(BundlePadding, OW))
> +      report_fatal_error("unable to write NOP sequence of " +
> +                         Twine(BundlePadding) + " bytes");
> +  }
> +
> +  // This variable (and its dummy usage) is to participate in the assert at
> +  // the end of the function.
>    uint64_t Start = OW->getStream().tell();
>    (void) Start;
>
> @@ -529,7 +592,8 @@
>    }
>    }
>
> -  assert(OW->getStream().tell() - Start == FragmentSize);
> +  assert(OW->getStream().tell() - Start == FragmentSize &&
> +         "The stream should advance by fragment size");
>  }
>
>  void MCAssembler::writeSectionData(const MCSectionData *SD,
> @@ -875,7 +939,9 @@
>    }
>
>    OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
> -     << " Offset:" << Offset << ">";
> +     << " Offset:" << Offset
> +     << " HasInstructions:" << hasInstructions()
> +     << " BundlePadding:" << getBundlePadding() << ">";
>
>    switch (getKind()) {
>    case MCFragment::FT_Align: {
> @@ -957,7 +1023,8 @@
>    raw_ostream &OS = llvm::errs();
>
>    OS << "<MCSectionData";
> -  OS << " Alignment:" << getAlignment() << " Fragments:[\n      ";
> +  OS << " Alignment:" << getAlignment()
> +     << " Fragments:[\n      ";
>    for (iterator it = begin(), ie = end(); it != ie; ++it) {
>      if (it != begin()) OS << ",\n      ";
>      it->dump();
>
> Modified: llvm/trunk/lib/MC/MCELFStreamer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCELFStreamer.cpp?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/lib/MC/MCELFStreamer.cpp (original)
> +++ llvm/trunk/lib/MC/MCELFStreamer.cpp Thu Dec 20 13:05:53 2012
> @@ -105,6 +105,9 @@
>  }
>
>  void MCELFStreamer::ChangeSection(const MCSection *Section) {
> +  MCSectionData *CurSection = getCurrentSectionData();
> +  if (CurSection && CurSection->isBundleLocked())
> +    report_fatal_error("Unterminated .bundle_lock when changing a section");
>    const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup();
>    if (Grp)
>      getAssembler().getOrCreateSymbolData(*Grp);
> @@ -262,10 +265,22 @@
>
>  void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
>                                    unsigned AddrSpace) {
> +  if (getCurrentSectionData()->isBundleLocked())
> +    report_fatal_error("Emitting values inside a locked bundle is forbidden");
>    fixSymbolsInTLSFixups(Value);
>    MCObjectStreamer::EmitValueImpl(Value, Size, AddrSpace);
>  }
>
> +void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment,
> +                                         int64_t Value,
> +                                         unsigned ValueSize,
> +                                         unsigned MaxBytesToEmit) {
> +  if (getCurrentSectionData()->isBundleLocked())
> +    report_fatal_error("Emitting values inside a locked bundle is forbidden");
> +  MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value,
> +                                         ValueSize, MaxBytesToEmit);
> +}
> +
>
>  // Add a symbol for the file name of this module. This is the second
>  // entry in the module's symbol table (the first being the null symbol).
> @@ -335,25 +350,91 @@
>  }
>
>  void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
> -  MCDataFragment *DF = getOrCreateDataFragment();
> -
> +  MCAssembler &Assembler = getAssembler();
>    SmallVector<MCFixup, 4> Fixups;
>    SmallString<256> Code;
>    raw_svector_ostream VecOS(Code);
> -  getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
> +  Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
>    VecOS.flush();
>
>    for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
>      fixSymbolsInTLSFixups(Fixups[i].getValue());
>
> +  // There are several possibilities here:
> +  //
> +  // If bundling is disabled, append the encoded instruction to the current data
> +  // fragment (or create a new such fragment if the current fragment is not a
> +  // data fragment).
> +  //
> +  // If bundling is enabled:
> +  // - If we're not in a bundle-locked group, emit the instruction into a data
> +  //   fragment of its own.
> +  // - If we're in a bundle-locked group, append the instruction to the current
> +  //   data fragment because we want all the instructions in a group to get into
> +  //   the same fragment. Be careful not to do that for the first instruction in
> +  //   the group, though.
> +  MCDataFragment *DF;
> +
> +  if (Assembler.isBundlingEnabled()) {
> +    MCSectionData *SD = getCurrentSectionData();
> +    if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst())
> +      DF = getOrCreateDataFragment();
> +    else
> +      DF = new MCDataFragment(SD);
> +
> +    // We're now emitting an instruction in a bundle group, so this flag has
> +    // to be turned off.
> +    SD->setBundleGroupBeforeFirstInst(false);
> +  } else {
> +    DF = getOrCreateDataFragment();
> +  }
> +
>    // Add the fixups and data.
>    for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
>      Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
>      DF->getFixups().push_back(Fixups[i]);
>    }
> +  DF->setHasInstructions(true);
>    DF->getContents().append(Code.begin(), Code.end());
>  }
>
> +void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
> +  assert(AlignPow2 <= 30 && "Invalid bundle alignment");
> +  MCAssembler &Assembler = getAssembler();
> +  if (Assembler.getBundleAlignSize() == 0 && AlignPow2 > 0)
> +    Assembler.setBundleAlignSize(1 << AlignPow2);
> +  else
> +    report_fatal_error(".bundle_align_mode should be only set once per file");
> +}
> +
> +void MCELFStreamer::EmitBundleLock() {
> +  MCSectionData *SD = getCurrentSectionData();
> +
> +  // Sanity checks
> +  //
> +  if (!getAssembler().isBundlingEnabled())
> +    report_fatal_error(".bundle_lock forbidden when bundling is disabled");
> +  else if (SD->isBundleLocked())
> +    report_fatal_error("Nesting of .bundle_lock is forbidden");
> +
> +  SD->setBundleLocked(true);
> +  SD->setBundleGroupBeforeFirstInst(true);
> +}
> +
> +void MCELFStreamer::EmitBundleUnlock() {
> +  MCSectionData *SD = getCurrentSectionData();
> +
> +  // Sanity checks
> +  if (!getAssembler().isBundlingEnabled())
> +    report_fatal_error(".bundle_unlock forbidden when bundling is disabled");
> +  else if (!SD->isBundleLocked())
> +    report_fatal_error(".bundle_unlock without matching lock");
> +  else if (SD->isBundleGroupBeforeFirstInst())
> +    report_fatal_error("Empty bundle-locked group is forbidden");
> +
> +  SD->setBundleLocked(false);
> +}
> +
>  void MCELFStreamer::FinishImpl() {
>    EmitFrames(true);
>
>
> Modified: llvm/trunk/lib/MC/MCNullStreamer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCNullStreamer.cpp?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/lib/MC/MCNullStreamer.cpp (original)
> +++ llvm/trunk/lib/MC/MCNullStreamer.cpp Thu Dec 20 13:05:53 2012
> @@ -95,6 +95,10 @@
>                                         StringRef FileName) {}
>      virtual void EmitInstruction(const MCInst &Inst) {}
>
> +    virtual void EmitBundleAlignMode(unsigned AlignPow2) {}
> +    virtual void EmitBundleLock() {}
> +    virtual void EmitBundleUnlock() {}
> +
>      virtual void FinishImpl() {}
>
>      virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
>
> Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
> +++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Thu Dec 20 13:05:53 2012
> @@ -180,21 +180,27 @@
>      if (Inst.getOperand(i).isExpr())
>        AddValueSymbols(Inst.getOperand(i).getExpr());
>
> -  getCurrentSectionData()->setHasInstructions(true);
> +  MCSectionData *SD = getCurrentSectionData();
> +  SD->setHasInstructions(true);
>
>    // Now that a machine instruction has been assembled into this section, make
>    // a line entry for any .loc directive that has been seen.
>    MCLineEntry::Make(this, getCurrentSection());
>
>    // If this instruction doesn't need relaxation, just emit it as data.
> -  if (!getAssembler().getBackend().mayNeedRelaxation(Inst)) {
> +  MCAssembler &Assembler = getAssembler();
> +  if (!Assembler.getBackend().mayNeedRelaxation(Inst)) {
>      EmitInstToData(Inst);
>      return;
>    }
>
> -  // Otherwise, if we are relaxing everything, relax the instruction as much as
> -  // possible and emit it as data.
> -  if (getAssembler().getRelaxAll()) {
> +  // Otherwise, relax and emit it as data if either:
> +  // - The RelaxAll flag was passed
> +  // - Bundling is enabled and this instruction is inside a bundle-locked
> +  //   group. We want to emit all such instructions into the same data
> +  //   fragment.
> +  if (Assembler.getRelaxAll() ||
> +      (Assembler.isBundlingEnabled() && SD->isBundleLocked())) {
>      MCInst Relaxed;
>      getAssembler().getBackend().relaxInstruction(Inst, Relaxed);
>      while (getAssembler().getBackend().mayNeedRelaxation(Relaxed))
> @@ -208,6 +214,8 @@
>  }
>
>  void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) {
> +  // Always create a new, separate fragment here, because its size can change
> +  // during relaxation.
>    MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData());
>
>    SmallString<128> Code;
> @@ -217,6 +225,21 @@
>    IF->getContents().append(Code.begin(), Code.end());
>  }
>
> +const char *BundlingNotImplementedMsg =
> +  "Aligned bundling is not implemented for this object format";
> +
> +void MCObjectStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
> +  llvm_unreachable(BundlingNotImplementedMsg);
> +}
> +
> +void MCObjectStreamer::EmitBundleLock() {
> +  llvm_unreachable(BundlingNotImplementedMsg);
> +}
> +
> +void MCObjectStreamer::EmitBundleUnlock() {
> +  llvm_unreachable(BundlingNotImplementedMsg);
> +}
> +
>  void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
>                                                  const MCSymbol *LastLabel,
>                                                  const MCSymbol *Label,
>
> Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
> +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Thu Dec 20 13:05:53 2012
> @@ -305,6 +305,13 @@
>    // ".align{,32}", ".p2align{,w,l}"
>    bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize);
>
> +  // ".bundle_align_mode"
> +  bool ParseDirectiveBundleAlignMode();
> +  // ".bundle_lock"
> +  bool ParseDirectiveBundleLock();
> +  // ".bundle_unlock"
> +  bool ParseDirectiveBundleUnlock();
> +
>    /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which
>    /// accepts a single symbol (which should be a label or an external).
>    bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr);
> @@ -1304,6 +1311,13 @@
>      if (IDVal == ".p2alignl")
>        return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
>
> +    if (IDVal == ".bundle_align_mode")
> +      return ParseDirectiveBundleAlignMode();
> +    if (IDVal == ".bundle_lock")
> +      return ParseDirectiveBundleLock();
> +    if (IDVal == ".bundle_unlock")
> +      return ParseDirectiveBundleUnlock();
> +
>      if (IDVal == ".org")
>        return ParseDirectiveOrg();
>
> @@ -2429,6 +2443,59 @@
>    return false;
>  }
>
> +
> +/// ParseDirectiveBundleAlignMode
> +/// ::= {.bundle_align_mode} expression
> +bool AsmParser::ParseDirectiveBundleAlignMode() {
> +  CheckForValidSection();
> +
> +  // Expect a single argument: an expression that evaluates to a constant
> +  // in the inclusive range 0-30.
> +  SMLoc ExprLoc = getLexer().getLoc();
> +  int64_t AlignSizePow2;
> +  if (ParseAbsoluteExpression(AlignSizePow2))
> +    return true;
> +  else if (getLexer().isNot(AsmToken::EndOfStatement))
> +    return TokError("unexpected token after expression in"
> +                    " '.bundle_align_mode' directive");
> +  else if (AlignSizePow2 < 0 || AlignSizePow2 > 30)
> +    return Error(ExprLoc,
> +                 "invalid bundle alignment size (expected between 0 and 30)");
> +
> +  Lex();
> +
> +  // Because of AlignSizePow2's verified range we can safely truncate it to
> +  // unsigned.
> +  getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
> +  return false;
> +}
> +
> +/// ParseDirectiveBundleLock
> +/// ::= {.bundle_lock}
> +bool AsmParser::ParseDirectiveBundleLock() {
> +  CheckForValidSection();
> +
> +  if (getLexer().isNot(AsmToken::EndOfStatement))
> +    return TokError("unexpected token in '.bundle_lock' directive");
> +  Lex();
> +
> +  getStreamer().EmitBundleLock();
> +  return false;
> +}
> +
> +/// ParseDirectiveBundleLock
> +/// ::= {.bundle_lock}
> +bool AsmParser::ParseDirectiveBundleUnlock() {
> +  CheckForValidSection();
> +
> +  if (getLexer().isNot(AsmToken::EndOfStatement))
> +    return TokError("unexpected token in '.bundle_unlock' directive");
> +  Lex();
> +
> +  getStreamer().EmitBundleUnlock();
> +  return false;
> +}
> +
>  /// ParseDirectiveSymbolAttribute
>  ///  ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
>  bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
>
> Modified: llvm/trunk/tools/lto/LTOModule.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/LTOModule.cpp?rev=170718&r1=170717&r2=170718&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lto/LTOModule.cpp (original)
> +++ llvm/trunk/tools/lto/LTOModule.cpp Thu Dec 20 13:05:53 2012
> @@ -765,6 +765,10 @@
>        markDefined(*Symbol);
>      }
>
> +    virtual void EmitBundleAlignMode(unsigned AlignPow2) {}
> +    virtual void EmitBundleLock() {}
> +    virtual void EmitBundleUnlock() {}
> +
>      // Noop calls.
>      virtual void ChangeSection(const MCSection *Section) {}
>      virtual void InitSections() {}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list