[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

Jim Grosbach grosbach at apple.com
Thu Dec 20 14:37:30 PST 2012


We're seeing this on some internal bots, too, when building clang itself with a just-built ToT clang.

Eli, do you think you'll be able to get this fixed soon, or should we revert temporarily to give you time to sort things out?

-Jim

On Dec 20, 2012, at 1:46 PM, Matt Beaumont-Gay <matthewbg at google.com> wrote:

> 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
> _______________________________________________
> 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