[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