diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/MC/MCELFStreamer.cpp | 25 |
2 files changed, 36 insertions, 12 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index bc78a298639..85d0c13c710 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -291,7 +291,9 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) : Section(&_Section), Ordinal(~UINT32_C(0)), Alignment(1), - BundleLockState(NotBundleLocked), BundleGroupBeforeFirstInst(false), + BundleLockState(NotBundleLocked), + BundleLockNestingDepth(0), + BundleGroupBeforeFirstInst(false), HasInstructions(false) { if (A) @@ -328,6 +330,25 @@ MCSectionData::getSubsectionInsertionPoint(unsigned Subsection) { return IP; } +void MCSectionData::setBundleLockState(BundleLockStateType NewState) { + if (NewState == NotBundleLocked) { + if (BundleLockNestingDepth == 0) { + report_fatal_error("Mismatched bundle_lock/unlock directives"); + } + if (--BundleLockNestingDepth == 0) { + BundleLockState = NotBundleLocked; + } + return; + } + + // If any of the directives is an align_to_end directive, the whole nested + // group is align_to_end. So don't downgrade from align_to_end to just locked. + if (BundleLockState != BundleLockedAlignToEnd) { + BundleLockState = NewState; + } + ++BundleLockNestingDepth; +} + /* *** */ MCSymbolData::MCSymbolData() : Symbol(nullptr) {} diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index 34049b7c967..4ef22d00224 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -453,11 +453,13 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst, } else { DF = new MCDataFragment(); insert(DF); - if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { - // If this is a new fragment created for a bundle-locked group, and the - // group was marked as "align_to_end", set a flag in the fragment. - DF->setAlignToBundleEnd(true); - } + } + if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { + // If this fragment is for a group marked "align_to_end", set a flag + // in the fragment. This can happen after the fragment has already been + // created if there are nested bundle_align groups and an inner one + // is the one marked align_to_end. + DF->setAlignToBundleEnd(true); } // We're now emitting an instruction in a bundle group, so this flag has @@ -479,10 +481,11 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst, void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) { assert(AlignPow2 <= 30 && "Invalid bundle alignment"); MCAssembler &Assembler = getAssembler(); - if (Assembler.getBundleAlignSize() == 0 && AlignPow2 > 0) - Assembler.setBundleAlignSize(1 << AlignPow2); + if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 || + Assembler.getBundleAlignSize() == 1U << AlignPow2)) + Assembler.setBundleAlignSize(1U << AlignPow2); else - report_fatal_error(".bundle_align_mode should be only set once per file"); + report_fatal_error(".bundle_align_mode cannot be changed once set"); } void MCELFStreamer::EmitBundleLock(bool AlignToEnd) { @@ -492,12 +495,12 @@ void MCELFStreamer::EmitBundleLock(bool AlignToEnd) { // 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"); + + if (!SD->isBundleLocked()) + SD->setBundleGroupBeforeFirstInst(true); SD->setBundleLockState(AlignToEnd ? MCSectionData::BundleLockedAlignToEnd : MCSectionData::BundleLocked); - SD->setBundleGroupBeforeFirstInst(true); } void MCELFStreamer::EmitBundleUnlock() { |