From e105cf91fb969fbe5e238c2389ffdf3279da3519 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 15 Jul 2025 19:36:19 -0700 Subject: [PATCH 01/39] MC: Remove bundle alignment mode The being-removed PNaCl has a Software Fault Isolation mechanism, which requires that certain instructions and groups of instructions do not cross a bundle boundary. When `.bundle_align_mode` is in effect, each instruction is placed in its own fragment, allowing flexible NOP padding. This feature has significantly complicated our refactoring of MCStreamer and MCFragment, leading to considerable effort spent untangling it (including flushPendingLabels (75006466296ed4b0f845cbbec4bf77c21de43b40), MCAssembler iteration improvement, and recent MCFragment refactoring). * Make MCObjectStreamer::emitInstToData non-virtual and delete MCELFStreamer::emitInstTodata * Delete MCELFStreamer::emitValueImpl and emitValueToAlignment Minor instructions:u decrease for both -O0 -g and -O3 builds https://llvm-compile-time-tracker.com/compare.php?from=c06d3a7b728293cbc53ff91239d6cd87c0982ffb&to=9b078c7f228bc5b6cdbfe839f751c9407f8aec3e&stat=instructions:u Pull Request: https://github.com/llvm/llvm-project/pull/148781 --- llvm/include/llvm/MC/MCAssembler.h | 23 - llvm/include/llvm/MC/MCELFStreamer.h | 12 - llvm/include/llvm/MC/MCObjectStreamer.h | 5 +- llvm/include/llvm/MC/MCSection.h | 45 - llvm/include/llvm/MC/MCStreamer.h | 13 - llvm/lib/MC/MCAsmStreamer.cpp | 21 - llvm/lib/MC/MCAssembler.cpp | 128 - llvm/lib/MC/MCELFStreamer.cpp | 150 - llvm/lib/MC/MCFragment.cpp | 8 +- llvm/lib/MC/MCObjectStreamer.cpp | 57 +- llvm/lib/MC/MCParser/AsmParser.cpp | 68 - llvm/lib/MC/MCSection.cpp | 24 +- llvm/lib/MC/MCStreamer.cpp | 3 - .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 4 - .../MC/ARM/AlignedBundling/group-bundle-arm.s | 48 - .../illegal-subtarget-change.s | 16 - .../test/MC/ARM/AlignedBundling/lit.local.cfg | 2 - .../AlignedBundling/pad-align-to-bundle-end.s | 41 - .../MC/ARM/AlignedBundling/subtarget-change.s | 33 - .../AsmParser/AArch64/directive-parse-err.s | 7 +- .../align-mode-argument-error.s | 8 - .../asm-printing-bundle-directives.s | 22 - .../autogen-inst-offset-align-to-end.s | 2899 ----------------- .../autogen-inst-offset-padding.s | 2674 --------------- .../bundle-group-too-large-error.s | 18 - .../bundle-lock-option-error.s | 11 - .../bundle-subtarget-change-error.s | 16 - .../X86/AlignedBundling/different-sections.s | 27 - .../test/MC/X86/AlignedBundling/labeloffset.s | 81 - .../test/MC/X86/AlignedBundling/lit.local.cfg | 2 - .../lock-without-bundle-mode-error.s | 10 - .../MC/X86/AlignedBundling/long-nop-pad.s | 31 - .../AlignedBundling/misaligned-bundle-group.s | 19 - .../X86/AlignedBundling/misaligned-bundle.s | 26 - llvm/test/MC/X86/AlignedBundling/nesting.s | 73 - .../AlignedBundling/pad-align-to-bundle-end.s | 35 - .../X86/AlignedBundling/pad-bundle-groups.s | 49 - .../X86/AlignedBundling/relax-at-bundle-end.s | 18 - .../AlignedBundling/relax-in-bundle-group.s | 44 - .../X86/AlignedBundling/section-alignment.s | 23 - .../AlignedBundling/single-inst-bundling.s | 52 - .../switch-section-locked-error.s | 16 - .../unlock-without-lock-error.s | 11 - llvm/test/MC/X86/align-branch-bundle.s | 21 - 44 files changed, 26 insertions(+), 6868 deletions(-) delete mode 100644 llvm/test/MC/ARM/AlignedBundling/group-bundle-arm.s delete mode 100644 llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s delete mode 100644 llvm/test/MC/ARM/AlignedBundling/lit.local.cfg delete mode 100644 llvm/test/MC/ARM/AlignedBundling/pad-align-to-bundle-end.s delete mode 100644 llvm/test/MC/ARM/AlignedBundling/subtarget-change.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/align-mode-argument-error.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/asm-printing-bundle-directives.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/autogen-inst-offset-padding.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/bundle-group-too-large-error.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/bundle-lock-option-error.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/different-sections.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/labeloffset.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/lit.local.cfg delete mode 100644 llvm/test/MC/X86/AlignedBundling/lock-without-bundle-mode-error.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/long-nop-pad.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/misaligned-bundle-group.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/misaligned-bundle.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/nesting.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/pad-align-to-bundle-end.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/pad-bundle-groups.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/relax-at-bundle-end.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/relax-in-bundle-group.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/section-alignment.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/single-inst-bundling.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/switch-section-locked-error.s delete mode 100644 llvm/test/MC/X86/AlignedBundling/unlock-without-lock-error.s delete mode 100644 llvm/test/MC/X86/align-branch-bundle.s diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 1015992cedf29..6b0d1b202e8c2 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -85,11 +85,6 @@ class MCAssembler { // refactoring too. mutable SmallPtrSet ThumbFuncs; - /// The bundle alignment size currently set in the assembler. - /// - /// By default it's 0, which means bundling is disabled. - unsigned BundleAlignSize = 0; - /// Evaluate a fixup to a relocatable expression and the value which should be /// placed into the fixup. /// @@ -143,8 +138,6 @@ class MCAssembler { /// Compute the effective fragment size. LLVM_ABI uint64_t computeFragmentSize(const MCFragment &F) const; - LLVM_ABI void layoutBundle(MCFragment *Prev, MCFragment *F) const; - // Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment &F) const { return F.Offset; } @@ -203,16 +196,6 @@ class MCAssembler { bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = 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; - } - const_iterator begin() const { return Sections.begin(); } const_iterator end() const { return Sections.end(); } @@ -226,12 +209,6 @@ class MCAssembler { LLVM_ABI bool registerSection(MCSection &Section); LLVM_ABI bool registerSymbol(const MCSymbol &Symbol); - /// Write the necessary bundle padding to \p OS. - /// Expects a fragment \p F containing instructions and its size \p FSize. - LLVM_ABI void writeFragmentPadding(raw_ostream &OS, - const MCEncodedFragment &F, - uint64_t FSize) const; - LLVM_ABI void reportError(SMLoc L, const Twine &Msg) const; // Record pending errors during layout iteration, as they may go away once the // layout is finalized. diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h index fa0b5cbde71d9..cf931e99acce1 100644 --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -65,13 +65,8 @@ class MCELFStreamer : public MCObjectStreamer { void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment) override; - void emitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc = SMLoc()) override; - void emitIdent(StringRef IdentString) override; - void emitValueToAlignment(Align, int64_t, uint8_t, unsigned) override; - void emitCGProfileEntry(const MCSymbolRefExpr *From, const MCSymbolRefExpr *To, uint64_t Count) override; @@ -79,10 +74,6 @@ class MCELFStreamer : public MCObjectStreamer { // target-specific code. void finishImpl() final; - void emitBundleAlignMode(Align Alignment) override; - void emitBundleLock(bool AlignToEnd) override; - void emitBundleUnlock() override; - /// ELF object attributes section emission support struct AttributeItem { // This structure holds all attributes, accounting for their string / @@ -151,9 +142,6 @@ class MCELFStreamer : public MCObjectStreamer { } private: - bool isBundleLocked() const; - void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; - void finalizeCGProfileEntry(const MCSymbolRefExpr *&S, uint64_t Offset); void finalizeCGProfile(); diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 2b42507d66920..5990d70a076f5 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -59,7 +59,7 @@ class MCObjectStreamer : public MCStreamer { DenseMap> pendingAssignments; - virtual void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &); + void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &); void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; void emitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI); @@ -127,9 +127,6 @@ class MCObjectStreamer : public MCStreamer { /// can change its size during relaxation. void emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &); - void emitBundleAlignMode(Align Alignment) override; - void emitBundleLock(bool AlignToEnd) override; - void emitBundleUnlock() override; void emitBytes(StringRef Data) override; void emitValueToAlignment(Align Alignment, int64_t Fill = 0, uint8_t FillLen = 1, diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index e9f3820319281..6c8fe1a8062f5 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -62,13 +62,6 @@ class LLVM_ABI MCSection { SV_CAS, // MCCAS }; - /// Express the state of bundle locked groups while emitting code. - enum BundleLockStateType { - NotBundleLocked, - BundleLocked, - BundleLockedAlignToEnd - }; - struct iterator { MCFragment *F = nullptr; iterator() = default; @@ -95,16 +88,6 @@ class LLVM_ABI MCSection { /// The section index in the assemblers section list. unsigned Ordinal = 0; - /// Keeping track of bundle-locked state. - BundleLockStateType BundleLockState = NotBundleLocked; - - /// Current nesting depth of bundle_lock directives. - unsigned BundleLockNestingDepth = 0; - - /// We've seen a bundle_lock directive but not its first instruction - /// yet. - bool BundleGroupBeforeFirstInst : 1; - /// Whether this section has had instructions emitted into it. bool HasInstructions : 1; @@ -170,17 +153,6 @@ class LLVM_ABI MCSection { unsigned getOrdinal() const { return Ordinal; } void setOrdinal(unsigned Value) { Ordinal = Value; } - BundleLockStateType getBundleLockState() const { return BundleLockState; } - void setBundleLockState(BundleLockStateType NewState); - bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } - - bool isBundleGroupBeforeFirstInst() const { - return BundleGroupBeforeFirstInst; - } - void setBundleGroupBeforeFirstInst(bool IsFirst) { - BundleGroupBeforeFirstInst = IsFirst; - } - bool hasInstructions() const { return HasInstructions; } void setHasInstructions(bool Value) { HasInstructions = Value; } @@ -260,7 +232,6 @@ class MCFragment { /// /// MCEncodedFragment bool HasInstructions : 1; - bool AlignToBundleEnd : 1; /// MCDataFragment bool LinkerRelaxable : 1; /// MCRelaxableFragment: x86-specific @@ -298,7 +269,6 @@ class MCFragment { /// Interface implemented by fragments that contain encoded instructions and/or /// data. class MCEncodedFragment : public MCFragment { - uint8_t BundlePadding = 0; uint32_t ContentStart = 0; uint32_t ContentEnd = 0; uint32_t FixupStart = 0; @@ -330,21 +300,6 @@ class MCEncodedFragment : public MCFragment { } } - /// Should this fragment be placed at the end of an aligned bundle? - bool alignToBundleEnd() const { return AlignToBundleEnd; } - void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } - - /// 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. - uint8_t getBundlePadding() const { return BundlePadding; } - - /// Set the padding size for this fragment. By default it's a no-op, - /// and only some fragments have a meaningful implementation. - void setBundlePadding(uint8_t N) { BundlePadding = N; } - /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. /// Guaranteed to be non-null if hasInstructions() == true const MCSubtargetInfo *getSubtargetInfo() const { return STI; } diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index a6eab17b4cf0f..df150701bb3c5 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -1081,19 +1081,6 @@ class LLVM_ABI MCStreamer { const MCPseudoProbeInlineStack &InlineStack, MCSymbol *FnSym); - /// Set the bundle alignment mode from now on in the section. - /// The value 1 means turn the bundle alignment off. - virtual void emitBundleAlignMode(Align Alignment); - - /// The following instructions are a bundle-locked group. - /// - /// \param AlignToEnd - If true, the bundle-locked group will be aligned to - /// the end of a bundle. - virtual void emitBundleLock(bool AlignToEnd); - - /// Ends a bundle-locked group. - virtual void emitBundleUnlock(); - /// 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. diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 53ea5cf0bf657..9b5194b98651d 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -409,10 +409,6 @@ class MCAsmStreamer final : public MCStreamer { const MCPseudoProbeInlineStack &InlineStack, MCSymbol *FnSym) override; - void emitBundleAlignMode(Align Alignment) override; - void emitBundleLock(bool AlignToEnd) override; - void emitBundleUnlock() override; - std::optional> emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc, const MCSubtargetInfo &STI) override; @@ -2484,23 +2480,6 @@ void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index, EmitEOL(); } -void MCAsmStreamer::emitBundleAlignMode(Align Alignment) { - OS << "\t.bundle_align_mode " << Log2(Alignment); - EmitEOL(); -} - -void MCAsmStreamer::emitBundleLock(bool AlignToEnd) { - OS << "\t.bundle_lock"; - if (AlignToEnd) - OS << " align_to_end"; - EmitEOL(); -} - -void MCAsmStreamer::emitBundleUnlock() { - OS << "\t.bundle_unlock"; - EmitEOL(); -} - std::optional> MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc, diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index fd8a8c3a79c9f..7f01e272a323e 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -94,7 +94,6 @@ void MCAssembler::reset() { Sections.clear(); Symbols.clear(); ThumbFuncs.clear(); - BundleAlignSize = 0; // reset objects owned by us if (getBackendPtr()) @@ -282,87 +281,6 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const { llvm_unreachable("invalid fragment kind"); } -// Compute the amount of padding required before the fragment \p F to -// obey bundling restrictions, where \p FOffset is the fragment's offset in -// its section and \p FSize is the fragment's size. -static uint64_t computeBundlePadding(unsigned BundleSize, - const MCEncodedFragment *F, - uint64_t FOffset, uint64_t FSize) { - uint64_t OffsetInBundle = FOffset & (BundleSize - 1); - uint64_t EndOfFragment = OffsetInBundle + FSize; - - // There are two kinds of bundling restrictions: - // - // 1) For alignToBundleEnd(), add padding to ensure that the fragment will - // *end* on a bundle boundary. - // 2) Otherwise, check if the fragment would cross a bundle boundary. If it - // would, add padding until the end of the bundle so that the fragment - // will start in a new one. - if (F->alignToBundleEnd()) { - // Three possibilities here: - // - // A) The fragment just happens to end at a bundle boundary, so we're good. - // B) The fragment ends before the current bundle boundary: pad it just - // enough to reach the boundary. - // C) The fragment ends after the current bundle boundary: pad it until it - // reaches the end of the next bundle boundary. - // - // Note: this code could be made shorter with some modulo trickery, but it's - // intentionally kept in its more explicit form for simplicity. - if (EndOfFragment == BundleSize) - return 0; - else if (EndOfFragment < BundleSize) - return BundleSize - EndOfFragment; - else { // EndOfFragment > BundleSize - return 2 * BundleSize - EndOfFragment; - } - } else if (OffsetInBundle > 0 && EndOfFragment > BundleSize) - return BundleSize - OffsetInBundle; - else - return 0; -} - -void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const { - // 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. - // - // ".align N" is an example of a directive that introduces multiple - // fragments. We could add a special case to handle ".align N" by emitting - // within-fragment padding (which would produce less padding when N is less - // than the bundle size), but for now we don't. - // - assert(isa(F) && - "Only MCEncodedFragment implementations have instructions"); - MCEncodedFragment *EF = cast(F); - uint64_t FSize = computeFragmentSize(*EF); - - if (FSize > getBundleAlignSize()) - report_fatal_error("Fragment can't be larger than a bundle size"); - - uint64_t RequiredBundlePadding = - computeBundlePadding(getBundleAlignSize(), EF, EF->Offset, FSize); - if (RequiredBundlePadding > UINT8_MAX) - report_fatal_error("Padding cannot exceed 255 bytes"); - EF->setBundlePadding(static_cast(RequiredBundlePadding)); - EF->Offset += RequiredBundlePadding; - if (auto *DF = dyn_cast_or_null(Prev)) - if (DF->getContents().empty()) - DF->Offset = EF->Offset; -} - // Simple getSymbolOffset helper for the non-variable case. static bool getLabelOffset(const MCAssembler &Asm, const MCSymbol &S, bool ReportError, uint64_t &Val) { @@ -480,41 +398,6 @@ bool MCAssembler::registerSymbol(const MCSymbol &Symbol) { return Changed; } -void MCAssembler::writeFragmentPadding(raw_ostream &OS, - const MCEncodedFragment &EF, - uint64_t FSize) const { - assert(getBackendPtr() && "Expected assembler backend"); - // Should NOP padding be written out before this fragment? - unsigned BundlePadding = EF.getBundlePadding(); - if (BundlePadding > 0) { - assert(isBundlingEnabled() && - "Writing bundle padding with disabled bundling"); - assert(EF.hasInstructions() && - "Writing bundle padding for a fragment without instructions"); - - unsigned TotalLength = BundlePadding + static_cast(FSize); - const MCSubtargetInfo *STI = EF.getSubtargetInfo(); - if (EF.alignToBundleEnd() && TotalLength > getBundleAlignSize()) { - // If the padding itself crosses a bundle boundary, it must be emitted - // in 2 pieces, since even nop instructions must not cross boundaries. - // v--------------v <- BundleAlignSize - // v---------v <- BundlePadding - // ---------------------------- - // | Prev |####|####| F | - // ---------------------------- - // ^-------------------^ <- TotalLength - unsigned DistanceToBoundary = TotalLength - getBundleAlignSize(); - if (!getBackend().writeNopData(OS, DistanceToBoundary, STI)) - report_fatal_error("unable to write NOP sequence of " + - Twine(DistanceToBoundary) + " bytes"); - BundlePadding -= DistanceToBoundary; - } - if (!getBackend().writeNopData(OS, BundlePadding, STI)) - report_fatal_error("unable to write NOP sequence of " + - Twine(BundlePadding) + " bytes"); - } -} - /// Write the fragment \p F to the output file. static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, const MCFragment &F) { @@ -523,9 +406,6 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, llvm::endianness Endian = Asm.getBackend().Endian; - if (const MCEncodedFragment *EF = dyn_cast(&F)) - Asm.writeFragmentPadding(OS, *EF, FragmentSize); - // This variable (and its dummy usage) is to participate in the assert at // the end of the function. uint64_t Start = OS.tell(); @@ -1101,17 +981,9 @@ bool MCAssembler::relaxFragment(MCFragment &F) { } void MCAssembler::layoutSection(MCSection &Sec) { - MCFragment *Prev = nullptr; uint64_t Offset = 0; for (MCFragment &F : Sec) { F.Offset = Offset; - if (LLVM_UNLIKELY(isBundlingEnabled())) { - if (F.hasInstructions()) { - layoutBundle(Prev, &F); - Offset = F.Offset; - } - Prev = &F; - } Offset += computeFragmentSize(F); } } diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index 4bc3f4642ea02..ecc77c6705267 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -48,10 +48,6 @@ ELFObjectWriter &MCELFStreamer::getWriter() { return static_cast(getAssembler().getWriter()); } -bool MCELFStreamer::isBundleLocked() const { - return getCurrentSectionOnly()->isBundleLocked(); -} - void MCELFStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) { MCContext &Ctx = getContext(); switchSection(Ctx.getObjectFileInfo()->getTextSection()); @@ -83,23 +79,8 @@ void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F, Symbol->setType(ELF::STT_TLS); } -// If bundle alignment is used and there are any instructions in the section, it -// needs to be aligned to at least the bundle size. -static void setSectionAlignmentForBundling(const MCAssembler &Assembler, - MCSection *Section) { - if (Assembler.isBundlingEnabled() && Section->hasInstructions()) - Section->ensureMinAlignment(Align(Assembler.getBundleAlignSize())); -} - void MCELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) { MCAssembler &Asm = getAssembler(); - if (auto *F = getCurrentFragment()) { - if (isBundleLocked()) - report_fatal_error("Unterminated .bundle_lock when changing a section"); - - // Ensure the previous section gets aligned if necessary. - setSectionAlignmentForBundling(Asm, F->getParent()); - } auto *SectionELF = static_cast(Section); const MCSymbol *Grp = SectionELF->getGroup(); if (Grp) @@ -313,22 +294,6 @@ void MCELFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size, emitCommonSymbol(Symbol, Size, ByteAlignment); } -void MCELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - if (isBundleLocked()) - report_fatal_error("Emitting values inside a locked bundle is forbidden"); - MCObjectStreamer::emitValueImpl(Value, Size, Loc); -} - -void MCELFStreamer::emitValueToAlignment(Align Alignment, int64_t Value, - uint8_t ValueSize, - unsigned MaxBytesToEmit) { - if (isBundleLocked()) - report_fatal_error("Emitting values inside a locked bundle is forbidden"); - MCObjectStreamer::emitValueToAlignment(Alignment, Value, ValueSize, - MaxBytesToEmit); -} - void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, const MCSymbolRefExpr *To, uint64_t Count) { @@ -391,117 +356,6 @@ void MCELFStreamer::finalizeCGProfile() { popSection(); } -// A fragment can only have one Subtarget, and when bundling is enabled we -// sometimes need to use the same fragment. We give an error if there -// are conflicting Subtargets. -static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI, - const MCSubtargetInfo *NewSTI) { - if (OldSTI && NewSTI && OldSTI != NewSTI) - report_fatal_error("A Bundle can only have one Subtarget."); -} - -void MCELFStreamer::emitInstToData(const MCInst &Inst, - const MCSubtargetInfo &STI) { - MCAssembler &Assembler = getAssembler(); - - // 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, or the Subtarget has changed). - // - // If bundling is enabled: - // - If we're not in a bundle-locked group, emit the instruction into a - // 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()) { - MCSection &Sec = *getCurrentSectionOnly(); - if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) { - // If we are bundle-locked, we re-use the current fragment. - // The bundle-locking directive ensures this is a new data fragment. - DF = cast(getCurrentFragment()); - CheckBundleSubtargets(DF->getSubtargetInfo(), &STI); - } else { - DF = getContext().allocFragment(); - insert(DF); - } - if (Sec.getBundleLockState() == MCSection::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 - // to be turned off. - Sec.setBundleGroupBeforeFirstInst(false); - } else { - DF = getOrCreateDataFragment(&STI); - } - - // Emit instruction directly into data fragment. - size_t FixupStartIndex = DF->getFixups().size(); - size_t CodeOffset = DF->getContents().size(); - SmallVector Fixups; - Assembler.getEmitter().encodeInstruction(Inst, DF->getContentsForAppending(), - Fixups, STI); - DF->doneAppending(); - if (!Fixups.empty()) - DF->appendFixups(Fixups); - - for (auto &Fixup : MutableArrayRef(DF->getFixups()).slice(FixupStartIndex)) { - Fixup.setOffset(Fixup.getOffset() + CodeOffset); - if (Fixup.isLinkerRelaxable()) { - DF->setLinkerRelaxable(); - getCurrentSectionOnly()->setLinkerRelaxable(); - } - } - - DF->setHasInstructions(STI); -} - -void MCELFStreamer::emitBundleAlignMode(Align Alignment) { - assert(Log2(Alignment) <= 30 && "Invalid bundle alignment"); - MCAssembler &Assembler = getAssembler(); - if (Alignment > 1 && (Assembler.getBundleAlignSize() == 0 || - Assembler.getBundleAlignSize() == Alignment.value())) - Assembler.setBundleAlignSize(Alignment.value()); - else - report_fatal_error(".bundle_align_mode cannot be changed once set"); -} - -void MCELFStreamer::emitBundleLock(bool AlignToEnd) { - MCSection &Sec = *getCurrentSectionOnly(); - - if (!getAssembler().isBundlingEnabled()) - report_fatal_error(".bundle_lock forbidden when bundling is disabled"); - - if (!isBundleLocked()) - Sec.setBundleGroupBeforeFirstInst(true); - - Sec.setBundleLockState(AlignToEnd ? MCSection::BundleLockedAlignToEnd - : MCSection::BundleLocked); -} - -void MCELFStreamer::emitBundleUnlock() { - MCSection &Sec = *getCurrentSectionOnly(); - - if (!getAssembler().isBundlingEnabled()) - report_fatal_error(".bundle_unlock forbidden when bundling is disabled"); - else if (!isBundleLocked()) - report_fatal_error(".bundle_unlock without matching lock"); - else if (Sec.isBundleGroupBeforeFirstInst()) - report_fatal_error("Empty bundle-locked group is forbidden"); - - Sec.setBundleLockState(MCSection::NotBundleLocked); -} - void MCELFStreamer::finishImpl() { // Emit the .gnu attributes section if any attributes have been added. if (!GNUAttributes.empty()) { @@ -510,10 +364,6 @@ void MCELFStreamer::finishImpl() { DummyAttributeSection, GNUAttributes); } - // Ensure the last section gets aligned if necessary. - if (MCFragment *F = getCurrentFragment()) - setSectionAlignmentForBundling(getAssembler(), F->getParent()); - finalizeCGProfile(); emitFrames(nullptr); diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index c59fabe5df1b9..c62abac2793e4 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -28,8 +28,8 @@ static_assert(std::is_trivially_destructible_v, "fragment classes must be trivially destructible"); MCFragment::MCFragment(FragmentType Kind, bool HasInstructions) - : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false), - LinkerRelaxable(false), AllowAutoPadding(false) {} + : Kind(Kind), HasInstructions(HasInstructions), LinkerRelaxable(false), + AllowAutoPadding(false) {} const MCSymbol *MCFragment::getAtom() const { return cast(Parent)->getAtom(LayoutOrder); @@ -59,10 +59,6 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { // clang-format on } - if (const auto *EF = dyn_cast(this)) - if (auto Pad = static_cast(EF->getBundlePadding())) - OS << " BundlePadding:" << Pad; - auto printFixups = [&](llvm::ArrayRef Fixups) { if (Fixups.empty()) return; diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 44a82f75576b6..4ab5e3e5d4b47 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -141,10 +141,6 @@ static bool canReuseDataFragment(const MCDataFragment &F, // instruction cannot be resolved at assemble-time. if (F.isLinkerRelaxable()) return false; - // When bundling is enabled, we don't want to add data to a fragment that - // already has instructions (see MCELFStreamer::emitInstToData for details) - if (Assembler.isBundlingEnabled()) - return false; // If the subtarget is changed mid fragment we start a new fragment to record // the new STI. return !STI || F.getSubtargetInfo() == STI; @@ -359,13 +355,8 @@ void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst, return; } - // 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() && Sec->isBundleLocked())) { + // Otherwise, relax and emit it as data if RelaxAll is specified. + if (Assembler.getRelaxAll()) { MCInst Relaxed = Inst; while (Backend.mayNeedRelaxation(Relaxed.getOpcode(), Relaxed.getOperands(), STI)) @@ -380,18 +371,27 @@ void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst, void MCObjectStreamer::emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) { - MCDataFragment *DF = getOrCreateDataFragment(); + MCDataFragment *F = getOrCreateDataFragment(&STI); + + // Append the instruction to the data fragment. + size_t FixupStartIndex = F->getFixups().size(); + size_t CodeOffset = F->getContents().size(); SmallVector Fixups; - SmallString<256> Code; - getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI); + getAssembler().getEmitter().encodeInstruction( + Inst, F->getContentsForAppending(), Fixups, STI); + F->doneAppending(); + if (!Fixups.empty()) + F->appendFixups(Fixups); - auto CodeOffset = DF->getContents().size(); - for (MCFixup &Fixup : Fixups) + for (auto &Fixup : MutableArrayRef(F->getFixups()).slice(FixupStartIndex)) { Fixup.setOffset(Fixup.getOffset() + CodeOffset); - if (!Fixups.empty()) - DF->appendFixups(Fixups); - DF->setHasInstructions(STI); - DF->appendContents(Code); + if (Fixup.isLinkerRelaxable()) { + F->setLinkerRelaxable(); + getCurrentSectionOnly()->setLinkerRelaxable(); + } + } + + F->setHasInstructions(STI); } void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, @@ -410,23 +410,6 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, IF->appendFixups(Fixups); } -#ifndef NDEBUG -static const char *const BundlingNotImplementedMsg = - "Aligned bundling is not implemented for this object format"; -#endif - -void MCObjectStreamer::emitBundleAlignMode(Align Alignment) { - llvm_unreachable(BundlingNotImplementedMsg); -} - -void MCObjectStreamer::emitBundleLock(bool AlignToEnd) { - llvm_unreachable(BundlingNotImplementedMsg); -} - -void MCObjectStreamer::emitBundleUnlock() { - llvm_unreachable(BundlingNotImplementedMsg); -} - void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 9fd6c05a846db..a36b2dea70ccf 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -421,9 +421,6 @@ class AsmParser : public MCAsmParser { DK_ORG, DK_FILL, DK_ENDR, - DK_BUNDLE_ALIGN_MODE, - DK_BUNDLE_LOCK, - DK_BUNDLE_UNLOCK, DK_ZERO, DK_EXTERN, DK_GLOBL, @@ -624,12 +621,6 @@ class AsmParser : public MCAsmParser { bool parseDirectiveMacrosOnOff(StringRef Directive); // alternate macro mode directives bool parseDirectiveAltmacro(StringRef Directive); - // ".bundle_align_mode" - bool parseDirectiveBundleAlignMode(); - // ".bundle_lock" - bool parseDirectiveBundleLock(); - // ".bundle_unlock" - bool parseDirectiveBundleUnlock(); // ".space", ".skip" bool parseDirectiveSpace(StringRef IDVal); @@ -2062,12 +2053,6 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveIrpc(IDLoc); case DK_ENDR: return parseDirectiveEndr(IDLoc); - case DK_BUNDLE_ALIGN_MODE: - return parseDirectiveBundleAlignMode(); - case DK_BUNDLE_LOCK: - return parseDirectiveBundleLock(); - case DK_BUNDLE_UNLOCK: - return parseDirectiveBundleUnlock(); case DK_SLEB128: return parseDirectiveLEB128(true); case DK_ULEB128: @@ -4779,56 +4764,6 @@ bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { return false; } -/// parseDirectiveBundleAlignMode -/// ::= {.bundle_align_mode} expression -bool AsmParser::parseDirectiveBundleAlignMode() { - // 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 (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) || - parseEOL() || - check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc, - "invalid bundle alignment size (expected between 0 and 30)")) - return true; - - getStreamer().emitBundleAlignMode(Align(1ULL << AlignSizePow2)); - return false; -} - -/// parseDirectiveBundleLock -/// ::= {.bundle_lock} [align_to_end] -bool AsmParser::parseDirectiveBundleLock() { - if (checkForValidSection()) - return true; - bool AlignToEnd = false; - - StringRef Option; - SMLoc Loc = getTok().getLoc(); - const char *kInvalidOptionError = - "invalid option for '.bundle_lock' directive"; - - if (!parseOptionalToken(AsmToken::EndOfStatement)) { - if (check(parseIdentifier(Option), Loc, kInvalidOptionError) || - check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL()) - return true; - AlignToEnd = true; - } - - getStreamer().emitBundleLock(AlignToEnd); - return false; -} - -/// parseDirectiveBundleLock -/// ::= {.bundle_lock} -bool AsmParser::parseDirectiveBundleUnlock() { - if (checkForValidSection() || parseEOL()) - return true; - - getStreamer().emitBundleUnlock(); - return false; -} - /// parseDirectiveSpace /// ::= (.skip | .space) expression [ , expression ] bool AsmParser::parseDirectiveSpace(StringRef IDVal) { @@ -5477,9 +5412,6 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".irp"] = DK_IRP; DirectiveKindMap[".irpc"] = DK_IRPC; DirectiveKindMap[".endr"] = DK_ENDR; - DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE; - DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK; - DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK; DirectiveKindMap[".if"] = DK_IF; DirectiveKindMap[".ifeq"] = DK_IFEQ; DirectiveKindMap[".ifge"] = DK_IFGE; diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index beb472b7c7deb..f1c81e90a0fe5 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -20,9 +20,8 @@ using namespace llvm; MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText, bool IsVirtual, MCSymbol *Begin) - : Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false), - IsRegistered(false), IsText(IsText), IsVirtual(IsVirtual), - LinkerRelaxable(false), Name(Name), Variant(V) { + : Begin(Begin), HasInstructions(false), IsRegistered(false), IsText(IsText), + IsVirtual(IsVirtual), LinkerRelaxable(false), Name(Name), Variant(V) { // The initial subsection number is 0. Create a fragment list. CurFragList = &Subsections.emplace_back(0u, FragList{}).second; } @@ -35,25 +34,6 @@ MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) { bool MCSection::hasEnded() const { return End && End->isInSection(); } -void MCSection::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; -} - StringRef MCSection::getVirtualSectionKind() const { return "virtual"; } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 6d2fb41760044..d814ab8880500 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1333,10 +1333,7 @@ void MCStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit) {} void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc) {} -void MCStreamer::emitBundleAlignMode(Align Alignment) {} -void MCStreamer::emitBundleLock(bool AlignToEnd) {} void MCStreamer::finishImpl() {} -void MCStreamer::emitBundleUnlock() {} bool MCStreamer::popSection() { if (SectionStack.size() <= 1) diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 54853e3f858e9..a94b2df617911 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -468,10 +468,6 @@ bool X86AsmBackend::canPadBranches(MCObjectStreamer &OS) const { if (!OS.getCurrentSectionOnly()->isText()) return false; - // To be Done: Currently don't deal with Bundle cases. - if (OS.getAssembler().isBundlingEnabled()) - return false; - // Branches only need to be aligned in 32-bit or 64-bit mode. if (!(STI.hasFeature(X86::Is64Bit) || STI.hasFeature(X86::Is32Bit))) return false; diff --git a/llvm/test/MC/ARM/AlignedBundling/group-bundle-arm.s b/llvm/test/MC/ARM/AlignedBundling/group-bundle-arm.s deleted file mode 100644 index ca78f2acc2894..0000000000000 --- a/llvm/test/MC/ARM/AlignedBundling/group-bundle-arm.s +++ /dev/null @@ -1,48 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple armv7-linux-gnueabi %s -o - \ -# RUN: | llvm-objdump --no-show-raw-insn --triple=armv7 -d - | FileCheck %s - -# On ARM each instruction is 4 bytes long so padding for individual -# instructions should not be inserted. However, for bundle-locked groups -# it can be. - - .syntax unified - .text - .bundle_align_mode 4 - - bx lr - and r1, r1, r2 - and r1, r1, r2 - .bundle_lock - bx r9 - bx r8 - .bundle_unlock -# CHECK: c: nop -# CHECK-NEXT: 10: bx -# CHECK-NEXT: 14: bx - - # pow2 here - .align 4 - bx lr - .bundle_lock - bx r9 - bx r9 - bx r9 - bx r8 - .bundle_unlock -# CHECK: 20: bx -# CHECK-NEXT: 24: nop -# CHECK-NEXT: 28: nop -# CHECK-NEXT: 2c: nop -# CHECK-NEXT: 30: bx - - .align 4 -foo: - b foo - .long 3892240112 - .long 3892240112 - .long 3892240112 - .long 3892240112 - .long 3892240112 - .long 3892240112 -# CHECK: 40: b - diff --git a/llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s b/llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s deleted file mode 100644 index e831ac5c2af06..0000000000000 --- a/llvm/test/MC/ARM/AlignedBundling/illegal-subtarget-change.s +++ /dev/null @@ -1,16 +0,0 @@ -# RUN: not --crash llvm-mc -filetype=obj -triple armv7-linux-gnueabi %s -o - 2>&1 | FileCheck %s - - # We cannot switch subtargets mid-bundle - .syntax unified - .text - .bundle_align_mode 4 - .arch armv4t - bx lr - .bundle_lock - bx lr - .arch armv7a - movt r0, #0xffff - movw r0, #0xffff - .bundle_unlock - bx lr -# CHECK: LLVM ERROR: A Bundle can only have one Subtarget. diff --git a/llvm/test/MC/ARM/AlignedBundling/lit.local.cfg b/llvm/test/MC/ARM/AlignedBundling/lit.local.cfg deleted file mode 100644 index 42bf50dcc13c3..0000000000000 --- a/llvm/test/MC/ARM/AlignedBundling/lit.local.cfg +++ /dev/null @@ -1,2 +0,0 @@ -if not "X86" in config.root.targets: - config.unsupported = True diff --git a/llvm/test/MC/ARM/AlignedBundling/pad-align-to-bundle-end.s b/llvm/test/MC/ARM/AlignedBundling/pad-align-to-bundle-end.s deleted file mode 100644 index c01c8c178afeb..0000000000000 --- a/llvm/test/MC/ARM/AlignedBundling/pad-align-to-bundle-end.s +++ /dev/null @@ -1,41 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple armv7-linux-gnueabi %s -o - \ -# RUN: | llvm-objdump --no-show-raw-insn --triple=armv7 -d - | FileCheck %s - - .syntax unified - .text - .bundle_align_mode 4 - - bx lr - and r1, r1, r2 - and r1, r1, r2 - .bundle_lock align_to_end - bx r9 - .bundle_unlock -# No padding required here because bx just happens to be in the -# right offset. -# CHECK: 8: and -# CHECK-NEXT: c: bx - - bx lr - and r1, r1, r2 - .bundle_lock align_to_end - bx r9 - .bundle_unlock -# A 4-byte padding is needed here -# CHECK: 18: nop -# CHECK-NEXT: 1c: bx - - bx lr - and r1, r1, r2 - .bundle_lock align_to_end - bx r9 - bx r9 - bx r9 - .bundle_unlock -# A 12-byte padding is needed here to push the group to the end of the next -# bundle -# CHECK: 28: nop -# CHECK-NEXT: 2c: nop -# CHECK-NEXT: 30: nop -# CHECK-NEXT: 34: bx - diff --git a/llvm/test/MC/ARM/AlignedBundling/subtarget-change.s b/llvm/test/MC/ARM/AlignedBundling/subtarget-change.s deleted file mode 100644 index 5672560376d46..0000000000000 --- a/llvm/test/MC/ARM/AlignedBundling/subtarget-change.s +++ /dev/null @@ -1,33 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple armv7-linux-gnueabi %s -o - \ -# RUN: | llvm-objdump --no-print-imm-hex --no-show-raw-insn --triple=armv7 -d - | FileCheck %s - - # We can switch subtargets with .arch outside of a bundle - .syntax unified - .text - .bundle_align_mode 4 - .arch armv4t - bx lr - .bundle_lock - and r1, r1, r1 - and r1, r1, r1 - .bundle_unlock - bx lr - - # We can switch subtargets at the start of a bundle - bx lr - .bundle_lock align_to_end - .arch armv7a - movt r0, #0xffff - movw r0, #0xffff - .bundle_unlock - bx lr - -# CHECK: 0: bx lr -# CHECK-NEXT: 4: and r1, r1, r1 -# CHECK-NEXT: 8: and r1, r1, r1 -# CHECK-NEXT: c: bx lr -# CHECK-NEXT: 10: bx lr -# CHECK-NEXT: 14: nop -# CHECK-NEXT: 18: movt r0, #65535 -# CHECK-NEXT: 1c: movw r0, #65535 -# CHECK-NEXT: 20: bx lr diff --git a/llvm/test/MC/AsmParser/AArch64/directive-parse-err.s b/llvm/test/MC/AsmParser/AArch64/directive-parse-err.s index 02cdfd7829198..5e2dd4adcdf8c 100644 --- a/llvm/test/MC/AsmParser/AArch64/directive-parse-err.s +++ b/llvm/test/MC/AsmParser/AArch64/directive-parse-err.s @@ -1,5 +1,5 @@ // RUN: not llvm-mc -triple aarch64 %s 2>&1 | FileCheck %s -// RUN: not llvm-mc -triple aarch64 %s 2>&1 | grep "error:" | count 60 +// RUN: not llvm-mc -triple aarch64 %s 2>&1 | grep "error:" | count 59 // CHECK: [[#@LINE+1]]:19: error: expected newline .equ ident1, 0 $ @@ -175,11 +175,6 @@ // CHECK-NOT: :[[#@LINE+1]]:{{[0-9]+}}: error: .cv_loc 1 1 // EOL COMMENT - // CHECK: [[#@LINE+1]]:28: error: expected newline - .bundle_lock align_to_end $ - // CHECK-NOT: [[#@LINE+1]]:{{[0-9]+}}: error: - .bundle_lock align_to_end // EOL COMMENT - // CHECK: [[#@LINE+1]]:11: error: invalid token in expression .sleb128 $ // CHECK-NOT: :[[#@LINE+1]]:{{[0-9]+}}: error: diff --git a/llvm/test/MC/X86/AlignedBundling/align-mode-argument-error.s b/llvm/test/MC/X86/AlignedBundling/align-mode-argument-error.s deleted file mode 100644 index 37c74c86f754e..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/align-mode-argument-error.s +++ /dev/null @@ -1,8 +0,0 @@ -# RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s - -# Missing .bundle_align_mode argument -# CHECK: error: unknown token - - .bundle_align_mode - imull $17, %ebx, %ebp - diff --git a/llvm/test/MC/X86/AlignedBundling/asm-printing-bundle-directives.s b/llvm/test/MC/X86/AlignedBundling/asm-printing-bundle-directives.s deleted file mode 100644 index 387e0fe59bf29..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/asm-printing-bundle-directives.s +++ /dev/null @@ -1,22 +0,0 @@ -# RUN: llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s - -# Just a simple test for the assembly emitter - making sure it emits back the -# bundling directives. - - .text -foo: - .bundle_align_mode 4 -# CHECK: .bundle_align_mode 4 - pushq %rbp - .bundle_lock -# CHECK: .bundle_lock - cmpl %r14d, %ebp - jle .L_ELSE - .bundle_unlock -# CHECK: .bundle_unlock - .bundle_lock align_to_end -# CHECK: .bundle_lock align_to_end - add %rbx, %rdx - .bundle_unlock - - diff --git a/llvm/test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s b/llvm/test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s deleted file mode 100644 index 6dabafc394e99..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s +++ /dev/null @@ -1,2899 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - \ -# RUN: | llvm-objdump --triple=i386 -d --no-show-raw-insn - | FileCheck %s - -# !!! This test is auto-generated from utils/testgen/mc-bundling-x86-gen.py !!! -# It tests that bundle-aligned grouping works correctly in MC. Read the -# source of the script for more details. - - .text - .bundle_align_mode 4 - - .align 32, 0x90 -INSTRLEN_1_OFFSET_0: - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 0: nop -# CHECK: f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 21: nop -# CHECK: 2f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 42: nop -# CHECK: 4f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 63: nop -# CHECK: 6f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 84: nop -# CHECK: 8f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: a5: nop -# CHECK: af: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: c6: nop -# CHECK: cf: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: e7: nop -# CHECK: ef: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 108: nop -# CHECK: 10f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 129: nop -# CHECK: 12f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 14a: nop -# CHECK: 14f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 16b: nop -# CHECK: 16f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 18c: nop -# CHECK: 18f: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ad: nop -# CHECK: 1af: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ce: nop -# CHECK: 1cf: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ef: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_0: - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 200: nop -# CHECK: 20e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 221: nop -# CHECK: 22e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 242: nop -# CHECK: 24e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 263: nop -# CHECK: 26e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 284: nop -# CHECK: 28e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 2a5: nop -# CHECK: 2ae: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 2c6: nop -# CHECK: 2ce: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 2e7: nop -# CHECK: 2ee: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 308: nop -# CHECK: 30e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 329: nop -# CHECK: 32e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 34a: nop -# CHECK: 34e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 36b: nop -# CHECK: 36e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 38c: nop -# CHECK: 38e: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 3ad: nop -# CHECK: 3ae: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 3ce: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 3ef: nop -# CHECK: 3f0: nop -# CHECK: 3fe: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_0: - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 400: nop -# CHECK: 40d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 421: nop -# CHECK: 42d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 442: nop -# CHECK: 44d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 463: nop -# CHECK: 46d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 484: nop -# CHECK: 48d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 4a5: nop -# CHECK: 4ad: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 4c6: nop -# CHECK: 4cd: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 4e7: nop -# CHECK: 4ed: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 508: nop -# CHECK: 50d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 529: nop -# CHECK: 52d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 54a: nop -# CHECK: 54d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 56b: nop -# CHECK: 56d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 58c: nop -# CHECK: 58d: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 5ad: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 5ce: nop -# CHECK: 5d0: nop -# CHECK: 5dd: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 5ef: nop -# CHECK: 5f0: nop -# CHECK: 5fd: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_0: - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 600: nop -# CHECK: 60c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 621: nop -# CHECK: 62c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 642: nop -# CHECK: 64c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 663: nop -# CHECK: 66c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 684: nop -# CHECK: 68c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 6a5: nop -# CHECK: 6ac: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 6c6: nop -# CHECK: 6cc: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 6e7: nop -# CHECK: 6ec: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 708: nop -# CHECK: 70c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 729: nop -# CHECK: 72c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 74a: nop -# CHECK: 74c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 76b: nop -# CHECK: 76c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 78c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 7ad: nop -# CHECK: 7b0: nop -# CHECK: 7bc: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 7ce: nop -# CHECK: 7d0: nop -# CHECK: 7dc: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 7ef: nop -# CHECK: 7f0: nop -# CHECK: 7fc: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_0: - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 800: nop -# CHECK: 80b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 821: nop -# CHECK: 82b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 842: nop -# CHECK: 84b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 863: nop -# CHECK: 86b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 884: nop -# CHECK: 88b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 8a5: nop -# CHECK: 8ab: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 8c6: nop -# CHECK: 8cb: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 8e7: nop -# CHECK: 8eb: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 908: nop -# CHECK: 90b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 929: nop -# CHECK: 92b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 94a: nop -# CHECK: 94b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 96b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 98c: nop -# CHECK: 990: nop -# CHECK: 99b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 9ad: nop -# CHECK: 9b0: nop -# CHECK: 9bb: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 9ce: nop -# CHECK: 9d0: nop -# CHECK: 9db: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 9ef: nop -# CHECK: 9f0: nop -# CHECK: 9fb: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_0: - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a00: nop -# CHECK: a0a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a21: nop -# CHECK: a2a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a42: nop -# CHECK: a4a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a63: nop -# CHECK: a6a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a84: nop -# CHECK: a8a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: aa5: nop -# CHECK: aaa: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: ac6: nop -# CHECK: aca: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: ae7: nop -# CHECK: aea: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b08: nop -# CHECK: b0a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b29: nop -# CHECK: b2a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b4a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b6b: nop -# CHECK: b70: nop -# CHECK: b7a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b8c: nop -# CHECK: b90: nop -# CHECK: b9a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: bad: nop -# CHECK: bb0: nop -# CHECK: bba: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: bce: nop -# CHECK: bd0: nop -# CHECK: bda: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: bef: nop -# CHECK: bf0: nop -# CHECK: bfa: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_0: - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c00: nop -# CHECK: c09: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c21: nop -# CHECK: c29: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c42: nop -# CHECK: c49: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c63: nop -# CHECK: c69: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c84: nop -# CHECK: c89: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: ca5: nop -# CHECK: ca9: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: cc6: nop -# CHECK: cc9: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: ce7: nop -# CHECK: ce9: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d08: nop -# CHECK: d09: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d29: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d4a: nop -# CHECK: d50: nop -# CHECK: d59: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d6b: nop -# CHECK: d70: nop -# CHECK: d79: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d8c: nop -# CHECK: d90: nop -# CHECK: d99: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: dad: nop -# CHECK: db0: nop -# CHECK: db9: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: dce: nop -# CHECK: dd0: nop -# CHECK: dd9: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: def: nop -# CHECK: df0: nop -# CHECK: df9: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_0: - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e00: nop -# CHECK: e08: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e21: nop -# CHECK: e28: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e42: nop -# CHECK: e48: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e63: nop -# CHECK: e68: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e84: nop -# CHECK: e88: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: ea5: nop -# CHECK: ea8: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: ec6: nop -# CHECK: ec8: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: ee7: nop -# CHECK: ee8: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f08: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f29: nop -# CHECK: f30: nop -# CHECK: f38: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f4a: nop -# CHECK: f50: nop -# CHECK: f58: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f6b: nop -# CHECK: f70: nop -# CHECK: f78: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f8c: nop -# CHECK: f90: nop -# CHECK: f98: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: fad: nop -# CHECK: fb0: nop -# CHECK: fb8: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: fce: nop -# CHECK: fd0: nop -# CHECK: fd8: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: fef: nop -# CHECK: ff0: nop -# CHECK: ff8: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_0: - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1000: nop -# CHECK: 1007: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1021: nop -# CHECK: 1027: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1042: nop -# CHECK: 1047: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1063: nop -# CHECK: 1067: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1084: nop -# CHECK: 1087: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 10a5: nop -# CHECK: 10a7: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 10c6: nop -# CHECK: 10c7: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 10e7: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1108: nop -# CHECK: 1110: nop -# CHECK: 1117: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1129: nop -# CHECK: 1130: nop -# CHECK: 1137: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 114a: nop -# CHECK: 1150: nop -# CHECK: 1157: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 116b: nop -# CHECK: 1170: nop -# CHECK: 1177: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 118c: nop -# CHECK: 1190: nop -# CHECK: 1197: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 11ad: nop -# CHECK: 11b0: nop -# CHECK: 11b7: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 11ce: nop -# CHECK: 11d0: nop -# CHECK: 11d7: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 11ef: nop -# CHECK: 11f0: nop -# CHECK: 11f7: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_0: - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1200: nop -# CHECK: 1206: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1221: nop -# CHECK: 1226: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1242: nop -# CHECK: 1246: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1263: nop -# CHECK: 1266: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1284: nop -# CHECK: 1286: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 12a5: nop -# CHECK: 12a6: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 12c6: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 12e7: nop -# CHECK: 12f0: nop -# CHECK: 12f6: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1308: nop -# CHECK: 1310: nop -# CHECK: 1316: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1329: nop -# CHECK: 1330: nop -# CHECK: 1336: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 134a: nop -# CHECK: 1350: nop -# CHECK: 1356: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 136b: nop -# CHECK: 1370: nop -# CHECK: 1376: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 138c: nop -# CHECK: 1390: nop -# CHECK: 1396: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 13ad: nop -# CHECK: 13b0: nop -# CHECK: 13b6: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 13ce: nop -# CHECK: 13d0: nop -# CHECK: 13d6: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 13ef: nop -# CHECK: 13f0: nop -# CHECK: 13f6: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_0: - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1400: nop -# CHECK: 1405: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1421: nop -# CHECK: 1425: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1442: nop -# CHECK: 1445: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1463: nop -# CHECK: 1465: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1484: nop -# CHECK: 1485: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 14a5: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 14c6: nop -# CHECK: 14d0: nop -# CHECK: 14d5: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 14e7: nop -# CHECK: 14f0: nop -# CHECK: 14f5: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1508: nop -# CHECK: 1510: nop -# CHECK: 1515: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1529: nop -# CHECK: 1530: nop -# CHECK: 1535: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 154a: nop -# CHECK: 1550: nop -# CHECK: 1555: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 156b: nop -# CHECK: 1570: nop -# CHECK: 1575: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 158c: nop -# CHECK: 1590: nop -# CHECK: 1595: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 15ad: nop -# CHECK: 15b0: nop -# CHECK: 15b5: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 15ce: nop -# CHECK: 15d0: nop -# CHECK: 15d5: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 15ef: nop -# CHECK: 15f0: nop -# CHECK: 15f5: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_0: - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1600: nop -# CHECK: 1604: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1621: nop -# CHECK: 1624: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1642: nop -# CHECK: 1644: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1663: nop -# CHECK: 1664: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1684: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 16a5: nop -# CHECK: 16b0: nop -# CHECK: 16b4: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 16c6: nop -# CHECK: 16d0: nop -# CHECK: 16d4: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 16e7: nop -# CHECK: 16f0: nop -# CHECK: 16f4: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1708: nop -# CHECK: 1710: nop -# CHECK: 1714: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1729: nop -# CHECK: 1730: nop -# CHECK: 1734: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 174a: nop -# CHECK: 1750: nop -# CHECK: 1754: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 176b: nop -# CHECK: 1770: nop -# CHECK: 1774: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 178c: nop -# CHECK: 1790: nop -# CHECK: 1794: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 17ad: nop -# CHECK: 17b0: nop -# CHECK: 17b4: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 17ce: nop -# CHECK: 17d0: nop -# CHECK: 17d4: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 17ef: nop -# CHECK: 17f0: nop -# CHECK: 17f4: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_0: - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1800: nop -# CHECK: 1803: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1821: nop -# CHECK: 1823: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1842: nop -# CHECK: 1843: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1863: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1884: nop -# CHECK: 1890: nop -# CHECK: 1893: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 18a5: nop -# CHECK: 18b0: nop -# CHECK: 18b3: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 18c6: nop -# CHECK: 18d0: nop -# CHECK: 18d3: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 18e7: nop -# CHECK: 18f0: nop -# CHECK: 18f3: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1908: nop -# CHECK: 1910: nop -# CHECK: 1913: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1929: nop -# CHECK: 1930: nop -# CHECK: 1933: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 194a: nop -# CHECK: 1950: nop -# CHECK: 1953: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 196b: nop -# CHECK: 1970: nop -# CHECK: 1973: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 198c: nop -# CHECK: 1990: nop -# CHECK: 1993: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 19ad: nop -# CHECK: 19b0: nop -# CHECK: 19b3: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 19ce: nop -# CHECK: 19d0: nop -# CHECK: 19d3: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 19ef: nop -# CHECK: 19f0: nop -# CHECK: 19f3: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_0: - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a00: nop -# CHECK: 1a02: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a21: nop -# CHECK: 1a22: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a42: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a63: nop -# CHECK: 1a70: nop -# CHECK: 1a72: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a84: nop -# CHECK: 1a90: nop -# CHECK: 1a92: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1aa5: nop -# CHECK: 1ab0: nop -# CHECK: 1ab2: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ac6: nop -# CHECK: 1ad0: nop -# CHECK: 1ad2: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ae7: nop -# CHECK: 1af0: nop -# CHECK: 1af2: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b08: nop -# CHECK: 1b10: nop -# CHECK: 1b12: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b29: nop -# CHECK: 1b30: nop -# CHECK: 1b32: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b4a: nop -# CHECK: 1b50: nop -# CHECK: 1b52: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b6b: nop -# CHECK: 1b70: nop -# CHECK: 1b72: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b8c: nop -# CHECK: 1b90: nop -# CHECK: 1b92: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1bad: nop -# CHECK: 1bb0: nop -# CHECK: 1bb2: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1bce: nop -# CHECK: 1bd0: nop -# CHECK: 1bd2: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1bef: nop -# CHECK: 1bf0: nop -# CHECK: 1bf2: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_0: - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c00: nop -# CHECK: 1c01: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c21: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c42: nop -# CHECK: 1c50: nop -# CHECK: 1c51: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c63: nop -# CHECK: 1c70: nop -# CHECK: 1c71: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c84: nop -# CHECK: 1c90: nop -# CHECK: 1c91: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ca5: nop -# CHECK: 1cb0: nop -# CHECK: 1cb1: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1cc6: nop -# CHECK: 1cd0: nop -# CHECK: 1cd1: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ce7: nop -# CHECK: 1cf0: nop -# CHECK: 1cf1: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d08: nop -# CHECK: 1d10: nop -# CHECK: 1d11: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d29: nop -# CHECK: 1d30: nop -# CHECK: 1d31: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d4a: nop -# CHECK: 1d50: nop -# CHECK: 1d51: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d6b: nop -# CHECK: 1d70: nop -# CHECK: 1d71: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d8c: nop -# CHECK: 1d90: nop -# CHECK: 1d91: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1dad: nop -# CHECK: 1db0: nop -# CHECK: 1db1: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1dce: nop -# CHECK: 1dd0: nop -# CHECK: 1dd1: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1def: nop -# CHECK: 1df0: nop -# CHECK: 1df1: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_0: - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e00: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e21: nop -# CHECK: 1e30: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e42: nop -# CHECK: 1e50: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e63: nop -# CHECK: 1e70: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e84: nop -# CHECK: 1e90: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ea5: nop -# CHECK: 1eb0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ec6: nop -# CHECK: 1ed0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ee7: nop -# CHECK: 1ef0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f08: nop -# CHECK: 1f10: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f29: nop -# CHECK: 1f30: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f4a: nop -# CHECK: 1f50: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f6b: nop -# CHECK: 1f70: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f8c: nop -# CHECK: 1f90: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1fad: nop -# CHECK: 1fb0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1fce: nop -# CHECK: 1fd0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock align_to_end - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1fef: nop -# CHECK: 1ff0: incl - diff --git a/llvm/test/MC/X86/AlignedBundling/autogen-inst-offset-padding.s b/llvm/test/MC/X86/AlignedBundling/autogen-inst-offset-padding.s deleted file mode 100644 index d486ec5fca00e..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/autogen-inst-offset-padding.s +++ /dev/null @@ -1,2674 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - \ -# RUN: | llvm-objdump --triple=i386 -d --no-show-raw-insn - | FileCheck %s - -# !!! This test is auto-generated from utils/testgen/mc-bundling-x86-gen.py !!! -# It tests that bundle-aligned grouping works correctly in MC. Read the -# source of the script for more details. - - .text - .bundle_align_mode 4 - - .align 32, 0x90 -INSTRLEN_1_OFFSET_0: - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 0: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 21: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 42: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 63: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 84: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: a5: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: c6: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: e7: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 108: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 129: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 14a: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 16b: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 18c: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ad: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ce: incl - - .align 32, 0x90 -INSTRLEN_1_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 1 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ef: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_0: - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 200: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 221: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 242: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 263: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 284: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 2a5: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 2c6: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 2e7: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 308: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 329: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 34a: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 36b: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 38c: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 3ad: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 3ce: incl - - .align 32, 0x90 -INSTRLEN_2_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 2 - inc %eax - .endr - .bundle_unlock -# CHECK: 3ef: nop -# CHECK: 3f0: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_0: - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 400: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 421: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 442: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 463: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 484: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 4a5: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 4c6: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 4e7: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 508: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 529: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 54a: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 56b: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 58c: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 5ad: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 5ce: nop -# CHECK: 5d0: incl - - .align 32, 0x90 -INSTRLEN_3_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 3 - inc %eax - .endr - .bundle_unlock -# CHECK: 5ef: nop -# CHECK: 5f0: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_0: - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 600: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 621: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 642: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 663: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 684: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 6a5: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 6c6: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 6e7: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 708: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 729: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 74a: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 76b: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 78c: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 7ad: nop -# CHECK: 7b0: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 7ce: nop -# CHECK: 7d0: incl - - .align 32, 0x90 -INSTRLEN_4_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 4 - inc %eax - .endr - .bundle_unlock -# CHECK: 7ef: nop -# CHECK: 7f0: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_0: - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 800: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 821: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 842: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 863: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 884: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 8a5: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 8c6: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 8e7: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 908: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 929: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 94a: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 96b: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 98c: nop -# CHECK: 990: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 9ad: nop -# CHECK: 9b0: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 9ce: nop -# CHECK: 9d0: incl - - .align 32, 0x90 -INSTRLEN_5_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 5 - inc %eax - .endr - .bundle_unlock -# CHECK: 9ef: nop -# CHECK: 9f0: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_0: - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a00: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a21: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a42: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a63: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: a84: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: aa5: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: ac6: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: ae7: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b08: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b29: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b4a: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b6b: nop -# CHECK: b70: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: b8c: nop -# CHECK: b90: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: bad: nop -# CHECK: bb0: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: bce: nop -# CHECK: bd0: incl - - .align 32, 0x90 -INSTRLEN_6_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 6 - inc %eax - .endr - .bundle_unlock -# CHECK: bef: nop -# CHECK: bf0: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_0: - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c00: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c21: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c42: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c63: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: c84: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: ca5: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: cc6: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: ce7: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d08: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d29: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d4a: nop -# CHECK: d50: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d6b: nop -# CHECK: d70: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: d8c: nop -# CHECK: d90: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: dad: nop -# CHECK: db0: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: dce: nop -# CHECK: dd0: incl - - .align 32, 0x90 -INSTRLEN_7_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 7 - inc %eax - .endr - .bundle_unlock -# CHECK: def: nop -# CHECK: df0: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_0: - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e00: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e21: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e42: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e63: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: e84: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: ea5: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: ec6: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: ee7: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f08: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f29: nop -# CHECK: f30: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f4a: nop -# CHECK: f50: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f6b: nop -# CHECK: f70: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: f8c: nop -# CHECK: f90: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: fad: nop -# CHECK: fb0: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: fce: nop -# CHECK: fd0: incl - - .align 32, 0x90 -INSTRLEN_8_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 8 - inc %eax - .endr - .bundle_unlock -# CHECK: fef: nop -# CHECK: ff0: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_0: - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1000: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1021: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1042: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1063: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1084: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 10a5: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 10c6: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 10e7: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1108: nop -# CHECK: 1110: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 1129: nop -# CHECK: 1130: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 114a: nop -# CHECK: 1150: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 116b: nop -# CHECK: 1170: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 118c: nop -# CHECK: 1190: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 11ad: nop -# CHECK: 11b0: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 11ce: nop -# CHECK: 11d0: incl - - .align 32, 0x90 -INSTRLEN_9_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 9 - inc %eax - .endr - .bundle_unlock -# CHECK: 11ef: nop -# CHECK: 11f0: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_0: - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1200: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1221: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1242: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1263: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1284: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 12a5: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 12c6: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 12e7: nop -# CHECK: 12f0: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1308: nop -# CHECK: 1310: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 1329: nop -# CHECK: 1330: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 134a: nop -# CHECK: 1350: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 136b: nop -# CHECK: 1370: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 138c: nop -# CHECK: 1390: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 13ad: nop -# CHECK: 13b0: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 13ce: nop -# CHECK: 13d0: incl - - .align 32, 0x90 -INSTRLEN_10_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 10 - inc %eax - .endr - .bundle_unlock -# CHECK: 13ef: nop -# CHECK: 13f0: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_0: - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1400: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1421: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1442: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1463: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1484: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 14a5: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 14c6: nop -# CHECK: 14d0: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 14e7: nop -# CHECK: 14f0: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1508: nop -# CHECK: 1510: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 1529: nop -# CHECK: 1530: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 154a: nop -# CHECK: 1550: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 156b: nop -# CHECK: 1570: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 158c: nop -# CHECK: 1590: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 15ad: nop -# CHECK: 15b0: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 15ce: nop -# CHECK: 15d0: incl - - .align 32, 0x90 -INSTRLEN_11_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 11 - inc %eax - .endr - .bundle_unlock -# CHECK: 15ef: nop -# CHECK: 15f0: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_0: - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1600: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1621: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1642: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1663: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1684: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 16a5: nop -# CHECK: 16b0: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 16c6: nop -# CHECK: 16d0: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 16e7: nop -# CHECK: 16f0: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1708: nop -# CHECK: 1710: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 1729: nop -# CHECK: 1730: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 174a: nop -# CHECK: 1750: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 176b: nop -# CHECK: 1770: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 178c: nop -# CHECK: 1790: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 17ad: nop -# CHECK: 17b0: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 17ce: nop -# CHECK: 17d0: incl - - .align 32, 0x90 -INSTRLEN_12_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 12 - inc %eax - .endr - .bundle_unlock -# CHECK: 17ef: nop -# CHECK: 17f0: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_0: - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1800: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1821: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1842: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1863: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1884: nop -# CHECK: 1890: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 18a5: nop -# CHECK: 18b0: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 18c6: nop -# CHECK: 18d0: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 18e7: nop -# CHECK: 18f0: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1908: nop -# CHECK: 1910: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 1929: nop -# CHECK: 1930: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 194a: nop -# CHECK: 1950: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 196b: nop -# CHECK: 1970: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 198c: nop -# CHECK: 1990: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 19ad: nop -# CHECK: 19b0: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 19ce: nop -# CHECK: 19d0: incl - - .align 32, 0x90 -INSTRLEN_13_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 13 - inc %eax - .endr - .bundle_unlock -# CHECK: 19ef: nop -# CHECK: 19f0: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_0: - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a00: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a21: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a42: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a63: nop -# CHECK: 1a70: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1a84: nop -# CHECK: 1a90: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1aa5: nop -# CHECK: 1ab0: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ac6: nop -# CHECK: 1ad0: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ae7: nop -# CHECK: 1af0: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b08: nop -# CHECK: 1b10: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b29: nop -# CHECK: 1b30: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b4a: nop -# CHECK: 1b50: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b6b: nop -# CHECK: 1b70: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1b8c: nop -# CHECK: 1b90: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1bad: nop -# CHECK: 1bb0: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1bce: nop -# CHECK: 1bd0: incl - - .align 32, 0x90 -INSTRLEN_14_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 14 - inc %eax - .endr - .bundle_unlock -# CHECK: 1bef: nop -# CHECK: 1bf0: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_0: - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c00: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c21: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c42: nop -# CHECK: 1c50: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c63: nop -# CHECK: 1c70: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1c84: nop -# CHECK: 1c90: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ca5: nop -# CHECK: 1cb0: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1cc6: nop -# CHECK: 1cd0: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ce7: nop -# CHECK: 1cf0: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d08: nop -# CHECK: 1d10: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d29: nop -# CHECK: 1d30: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d4a: nop -# CHECK: 1d50: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d6b: nop -# CHECK: 1d70: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1d8c: nop -# CHECK: 1d90: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1dad: nop -# CHECK: 1db0: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1dce: nop -# CHECK: 1dd0: incl - - .align 32, 0x90 -INSTRLEN_15_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 15 - inc %eax - .endr - .bundle_unlock -# CHECK: 1def: nop -# CHECK: 1df0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_0: - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e00: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_1: - .fill 1, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e21: nop -# CHECK: 1e30: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_2: - .fill 2, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e42: nop -# CHECK: 1e50: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_3: - .fill 3, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e63: nop -# CHECK: 1e70: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_4: - .fill 4, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1e84: nop -# CHECK: 1e90: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_5: - .fill 5, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ea5: nop -# CHECK: 1eb0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_6: - .fill 6, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ec6: nop -# CHECK: 1ed0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_7: - .fill 7, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1ee7: nop -# CHECK: 1ef0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_8: - .fill 8, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f08: nop -# CHECK: 1f10: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_9: - .fill 9, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f29: nop -# CHECK: 1f30: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_10: - .fill 10, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f4a: nop -# CHECK: 1f50: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_11: - .fill 11, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f6b: nop -# CHECK: 1f70: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_12: - .fill 12, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1f8c: nop -# CHECK: 1f90: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_13: - .fill 13, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1fad: nop -# CHECK: 1fb0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_14: - .fill 14, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1fce: nop -# CHECK: 1fd0: incl - - .align 32, 0x90 -INSTRLEN_16_OFFSET_15: - .fill 15, 1, 0x90 - .bundle_lock - .rept 16 - inc %eax - .endr - .bundle_unlock -# CHECK: 1fef: nop -# CHECK: 1ff0: incl - diff --git a/llvm/test/MC/X86/AlignedBundling/bundle-group-too-large-error.s b/llvm/test/MC/X86/AlignedBundling/bundle-group-too-large-error.s deleted file mode 100644 index 697b8bf6ab6c0..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/bundle-group-too-large-error.s +++ /dev/null @@ -1,18 +0,0 @@ -# RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s -# RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mc-relax-all %s -o - 2>&1 | FileCheck %s - -# CHECK: ERROR: Fragment can't be larger than a bundle size - - .text -foo: - .bundle_align_mode 4 - pushq %rbp - - .bundle_lock - pushq %r14 - callq bar - callq bar - callq bar - callq bar - .bundle_unlock - diff --git a/llvm/test/MC/X86/AlignedBundling/bundle-lock-option-error.s b/llvm/test/MC/X86/AlignedBundling/bundle-lock-option-error.s deleted file mode 100644 index b849d2b333007..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/bundle-lock-option-error.s +++ /dev/null @@ -1,11 +0,0 @@ -# RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s - -# Missing .bundle_align_mode argument -# CHECK: error: invalid option - - .bundle_align_mode 4 - .bundle_lock 5 - imull $17, %ebx, %ebp - .bundle_unlock - - diff --git a/llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s b/llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s deleted file mode 100644 index c02d0d6b19b4e..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/bundle-subtarget-change-error.s +++ /dev/null @@ -1,16 +0,0 @@ -# RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro %s -o - 2>&1 | FileCheck %s -# RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - 2>&1 | FileCheck %s - -# Switching mode will change subtarget, which we can't do within a bundle - .text - .code64 - .bundle_align_mode 4 -foo: - pushq %rbp - .bundle_lock - addl %ebp, %eax - .code32 - movb $0x0, (%si) - .bundle_unlock - -CHECK: LLVM ERROR: A Bundle can only have one Subtarget. diff --git a/llvm/test/MC/X86/AlignedBundling/different-sections.s b/llvm/test/MC/X86/AlignedBundling/different-sections.s deleted file mode 100644 index bc4f20132dbe7..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/different-sections.s +++ /dev/null @@ -1,27 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s - -# Test two different executable sections with bundling. - - .bundle_align_mode 3 - .section text1, "x" -# CHECK: section text1 - imull $17, %ebx, %ebp - imull $17, %ebx, %ebp - - imull $17, %ebx, %ebp -# CHECK: 6: nop -# CHECK-NEXT: 8: imull - - .section text2, "x" -# CHECK: section text2 - imull $17, %ebx, %ebp - imull $17, %ebx, %ebp - - imull $17, %ebx, %ebp -# CHECK: 6: nop -# CHECK-NEXT: 8: imull - - diff --git a/llvm/test/MC/X86/AlignedBundling/labeloffset.s b/llvm/test/MC/X86/AlignedBundling/labeloffset.s deleted file mode 100644 index 7f6150a8aa17c..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/labeloffset.s +++ /dev/null @@ -1,81 +0,0 @@ -# RUN: llvm-mc -triple=i686-linux -filetype=obj %s -o - | \ -# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn -r - | FileCheck %s - - .bundle_align_mode 5 - .text - .globl main - .align 32, 0x90 - .type main,@function -main: # @main -# CHECK-LABEL:
: -# Call + pop sequence for determining the PIC base. - .bundle_lock align_to_end - calll .L0$pb - .bundle_unlock -.L0$pb: - popl %eax -# CHECK: 20: popl -# 26 bytes of instructions between the pop and the use of the pic base symbol. - movl $3, 2(%ebx, %ebx) - movl $3, 2(%ebx, %ebx) - movl $3, 2(%ebx, %ebx) - hlt - hlt -# CHECK: nop -.Ltmp0: - addl (.Ltmp0-.L0$pb), %eax -# The addl has bundle padding to push it from 0x3b to 0x40. -# The difference between the labels should be 0x20 (0x40-0x20) not 0x1b -# (0x3b-0x20) -# CHECK: 40: addl 32, %eax - popl %ecx - jmp *%ecx - - -# Also make sure it works with a non-relaxable instruction (cmp vs add) -# and for 2 adjacent labels that both point to the correct instruction - .section .text.bar, "ax" - .globl bar - .align 32, 0x90 - .type bar,@function -bar: -# CHECK-LABEL: bar: - .bundle_lock align_to_end - calll .L1$pb - .bundle_unlock -.L1$pb: - popl %eax -# CHECK: 20: popl -# 26 bytes of instructions between the pop and the use of the pic base symbol. - movl $3, 2(%ebx, %ebx) - movl $3, 2(%ebx, %ebx) - movl $3, 2(%ebx, %ebx) - hlt - hlt -# CHECK: nop -.Ltmp1: -.Ltmp2: - cmpl %eax, .Ltmp1 -# CHECK: 40: cmpl %eax, 64 - cmpl %eax, (.Ltmp2-.L1$pb) -# CHECK: 46: cmpl %eax, 32 - popl %ecx - jmp *%ecx - - -# Switch sections in the middle of a function - .section .text.foo, "ax" - .globl foo - .align 32, 0x90 - .type foo,@function -# CHECK-LABEL: foo: -foo: - inc %eax -tmp3: - .rodata - .type obj,@object - .comm obj,4,4 - .section .text.foo - inc %eax -# CHECK: : -# CHECK-NEXT: 1: incl diff --git a/llvm/test/MC/X86/AlignedBundling/lit.local.cfg b/llvm/test/MC/X86/AlignedBundling/lit.local.cfg deleted file mode 100644 index 42bf50dcc13c3..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/lit.local.cfg +++ /dev/null @@ -1,2 +0,0 @@ -if not "X86" in config.root.targets: - config.unsupported = True diff --git a/llvm/test/MC/X86/AlignedBundling/lock-without-bundle-mode-error.s b/llvm/test/MC/X86/AlignedBundling/lock-without-bundle-mode-error.s deleted file mode 100644 index 65ee2d5b9f385..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/lock-without-bundle-mode-error.s +++ /dev/null @@ -1,10 +0,0 @@ -# RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s - -# .bundle_lock can't come without a .bundle_align_mode before it - -# CHECK: ERROR: .bundle_lock forbidden when bundling is disabled - - imull $17, %ebx, %ebp - .bundle_lock - - diff --git a/llvm/test/MC/X86/AlignedBundling/long-nop-pad.s b/llvm/test/MC/X86/AlignedBundling/long-nop-pad.s deleted file mode 100644 index 439915dfd0b5b..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/long-nop-pad.s +++ /dev/null @@ -1,31 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s - -# Test that long nops are generated for padding where possible. - - .text -foo: - .bundle_align_mode 5 - -# This callq instruction is 5 bytes long - .bundle_lock align_to_end - callq bar - .bundle_unlock -# To align this group to a bundle end, we need a two 10-byte NOPs and a 7-byte NOP. -# CHECK: 0: nop -# CHECK-NEXT: a: nop -# CHECK-NEXT: 14: nop -# CHECK: 1b: callq - -# This push instruction is 1 byte long - .bundle_lock align_to_end - push %rax - .bundle_unlock -# To align this group to a bundle end, we need three 10-byte NOPs, and a 1-byte. -# CHECK: 20: nop -# CHECK-NEXT: 2a: nop -# CHECK-NEXT: 34: nop -# CHECK-NEXT: 3e: nop -# CHECK-NEXT: 3f: pushq diff --git a/llvm/test/MC/X86/AlignedBundling/misaligned-bundle-group.s b/llvm/test/MC/X86/AlignedBundling/misaligned-bundle-group.s deleted file mode 100644 index 92bd9ec016bd5..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/misaligned-bundle-group.s +++ /dev/null @@ -1,19 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple i686-pc-linux-gnu -mcpu=pentiumpro %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - \ -# RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-OPT %s -# RUN: llvm-mc -filetype=obj -triple i686-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - \ -# RUN: | FileCheck --check-prefixes=CHECK,CHECK-OPT %s - - .text -foo: - .bundle_align_mode 5 - push %ebp # 1 byte - .align 16 - .bundle_lock align_to_end -# CHECK: 1: nopw %cs:(%eax,%eax) -# CHECK: 10: nopw %cs:(%eax,%eax) -# CHECK-OPT: 1b: calll 0x1c - calll bar # 5 bytes - .bundle_unlock - ret # 1 byte diff --git a/llvm/test/MC/X86/AlignedBundling/misaligned-bundle.s b/llvm/test/MC/X86/AlignedBundling/misaligned-bundle.s deleted file mode 100644 index 0bf5cfd802be9..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/misaligned-bundle.s +++ /dev/null @@ -1,26 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple i686-pc-linux-gnu -mcpu=pentiumpro %s -o - \ -# RUN: | llvm-objdump --no-print-imm-hex -d --no-show-raw-insn - \ -# RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-OPT %s -# RUN: llvm-mc -filetype=obj -triple i686-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - \ -# RUN: | llvm-objdump --no-print-imm-hex -d --no-show-raw-insn - \ -# RUN: | FileCheck --check-prefixes=CHECK,CHECK-OPT %s - - .text -foo: - .bundle_align_mode 5 - push %ebp # 1 byte - .align 16 -# CHECK: 1: nopw %cs:(%eax,%eax) -# CHECK-OPT: 10: movl $1, (%esp) - movl $0x1, (%esp) # 7 bytes - movl $0x1, (%esp) # 7 bytes -# CHECK-OPT: 1e: nop - movl $0x2, 0x1(%esp) # 8 bytes - movl $0x2, 0x1(%esp) # 8 bytes - movl $0x2, 0x1(%esp) # 8 bytes - movl $0x2, (%esp) # 7 bytes -# CHECK-OPT: 3f: nop -# CHECK-OPT: 40: movl $3, (%esp) - movl $0x3, (%esp) # 7 bytes - movl $0x3, (%esp) # 7 bytes - ret diff --git a/llvm/test/MC/X86/AlignedBundling/nesting.s b/llvm/test/MC/X86/AlignedBundling/nesting.s deleted file mode 100644 index e107a413521b3..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/nesting.s +++ /dev/null @@ -1,73 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s - -# Will be bundle-aligning to 16 byte boundaries - .bundle_align_mode 4 - .text -# CHECK-LABEL: : -.type foo,@function -foo: -# Test that bundle alignment mode can be set more than once. - .bundle_align_mode 4 -# Each of these callq instructions is 5 bytes long - callq bar - callq bar - .bundle_lock - .bundle_lock - callq bar - callq bar - .bundle_unlock - .bundle_unlock -# CHECK: 10: callq {{.*}} -# CHECK-NEXT: 15: callq {{.*}} - - .p2align 4 -# CHECK-LABEL: : -.type bar,@function -bar: - callq foo - callq foo -# Check that the callqs get bundled together, and that the whole group is -# align_to_end - .bundle_lock - callq bar - .bundle_lock align_to_end - callq bar - .bundle_unlock - .bundle_unlock -# CHECK: 36: callq {{.*}} -# CHECK-NEXT: 3b: callq {{.*}} - -# CHECK-LABEL: : -.type baz,@function -baz: - callq foo - callq foo -# Check that the callqs get bundled together, and that the whole group is -# align_to_end (with the outer directive marked align_to_end) - .bundle_lock align_to_end - callq bar - .bundle_lock - callq bar - .bundle_unlock - .bundle_unlock -# CHECK: 56: callq {{.*}} -# CHECK-NEXT: 5b: callq {{.*}} - -# CHECK-LABEL: quux -.type quux,@function -quux: - callq bar - callq bar - .bundle_lock - .bundle_lock - callq bar - .bundle_unlock - callq bar - .bundle_unlock -# Check that the calls are bundled together when the second one is after the -# inner nest is closed. -# CHECK: 70: callq {{.*}} -# CHECK-NEXT: 75: callq {{.*}} diff --git a/llvm/test/MC/X86/AlignedBundling/pad-align-to-bundle-end.s b/llvm/test/MC/X86/AlignedBundling/pad-align-to-bundle-end.s deleted file mode 100644 index d725724f8fd44..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/pad-align-to-bundle-end.s +++ /dev/null @@ -1,35 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s - -# Test some variations of padding to the end of a bundle. - - .text -foo: - .bundle_align_mode 4 - -# Each of these callq instructions is 5 bytes long - callq bar - callq bar - .bundle_lock align_to_end - callq bar - .bundle_unlock -# To align this group to a bundle end, we need a 1-byte NOP. -# CHECK: a: nop -# CHECK-NEXT: b: callq - - callq bar - callq bar - .bundle_lock align_to_end - callq bar - callq bar - .bundle_unlock -# Here we have to pad until the end of the *next* boundary because -# otherwise the group crosses a boundary. -# CHECK: 1a: nop -# The nop sequence may be implemented as one instruction or many, but if -# it's one instruction, that instruction cannot itself cross the boundary. -# CHECK: 20: nop -# CHECK-NEXT: 26: callq -# CHECK-NEXT: 2b: callq diff --git a/llvm/test/MC/X86/AlignedBundling/pad-bundle-groups.s b/llvm/test/MC/X86/AlignedBundling/pad-bundle-groups.s deleted file mode 100644 index 9e07b5994864b..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/pad-bundle-groups.s +++ /dev/null @@ -1,49 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s - -# Test some variations of padding for bundle-locked groups. - - .text -foo: - .bundle_align_mode 4 - -# Each of these callq instructions is 5 bytes long - callq bar - callq bar - - .bundle_lock - callq bar - callq bar - .bundle_unlock -# We'll need a 6-byte NOP before this group -# CHECK: a: nop -# CHECK-NEXT: 10: callq -# CHECK-NEXT: 15: callq - - .bundle_lock - callq bar - callq bar - .bundle_unlock -# Same here -# CHECK: 1a: nop -# CHECK-NEXT: 20: callq -# CHECK-NEXT: 25: callq - - .align 16, 0x90 - callq bar - .bundle_lock - callq bar - callq bar - callq bar - .bundle_unlock -# And here we'll need a 10-byte NOP + 1-byte NOP -# CHECK: 30: callq -# CHECK: 35: nop -# CHECK: 3f: nop -# CHECK-NEXT: 40: callq -# CHECK-NEXT: 45: callq - - - diff --git a/llvm/test/MC/X86/AlignedBundling/relax-at-bundle-end.s b/llvm/test/MC/X86/AlignedBundling/relax-at-bundle-end.s deleted file mode 100644 index 2c510f796e19f..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/relax-at-bundle-end.s +++ /dev/null @@ -1,18 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck %s - -# Test that an instruction near a bundle end gets properly padded -# after it is relaxed. -.text -foo: - .bundle_align_mode 5 - .rept 29 - push %rax - .endr -# CHECK: 1c: push -# CHECK: 1d: nop -# CHECK: 20: jne - jne 0x100 - diff --git a/llvm/test/MC/X86/AlignedBundling/relax-in-bundle-group.s b/llvm/test/MC/X86/AlignedBundling/relax-in-bundle-group.s deleted file mode 100644 index 2419a02f9ab74..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/relax-in-bundle-group.s +++ /dev/null @@ -1,44 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro %s -o - \ -# RUN: | llvm-objdump -d - | FileCheck %s -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d - | FileCheck %s - -# Test that instructions inside bundle-locked groups are relaxed even if their -# fixup is short enough not to warrant relaxation on its own. - - .text -foo: - .bundle_align_mode 4 - pushq %rbp - - movl %edi, %ebx - callq bar - movl %eax, %r14d - imull $17, %ebx, %ebp - movl %ebx, %edi - callq bar - cmpl %r14d, %ebp - .bundle_lock - - jle .L_ELSE -# This group would've started at 0x18 and is too long, so a chunky NOP padding -# is inserted to push it to 0x20. -# CHECK: 18: {{[a-f0-9 ]+}} nopl - -# The long encoding for JLE should be used here even though its target is close -# CHECK-NEXT: 20: 0f 8e - - addl %ebp, %eax - - jmp .L_RET -# Same for the JMP -# CHECK: 28: e9 - - .bundle_unlock - -.L_ELSE: - imull %ebx, %eax -.L_RET: - - popq %rbx - diff --git a/llvm/test/MC/X86/AlignedBundling/section-alignment.s b/llvm/test/MC/X86/AlignedBundling/section-alignment.s deleted file mode 100644 index d5277d194576e..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/section-alignment.s +++ /dev/null @@ -1,23 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - \ -# RUN: | llvm-readobj --sections - | FileCheck %s - -# Test that bundle-aligned sections with instructions are aligned - - .bundle_align_mode 5 -# CHECK: Sections -# Check that the empty .text section has the default alignment -# CHECK-LABEL: Name: .text -# CHECK-NOT: Name -# CHECK: AddressAlignment: 4 - - .section text1, "x" - imull $17, %ebx, %ebp -# CHECK-LABEL: Name: text1 -# CHECK-NOT: Name -# CHECK: AddressAlignment: 32 - - .section text2, "x" - imull $17, %ebx, %ebp -# CHECK-LABEL: Name: text2 -# CHECK-NOT: Name -# CHECK: AddressAlignment: 32 diff --git a/llvm/test/MC/X86/AlignedBundling/single-inst-bundling.s b/llvm/test/MC/X86/AlignedBundling/single-inst-bundling.s deleted file mode 100644 index 1bcd010240ae3..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/single-inst-bundling.s +++ /dev/null @@ -1,52 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-OPT %s -# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu -mcpu=pentiumpro -mc-relax-all %s -o - \ -# RUN: | llvm-objdump -d --no-show-raw-insn - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-RELAX %s - -# Test simple NOP insertion for single instructions. - - .text -foo: - # Will be bundle-aligning to 16 byte boundaries - .bundle_align_mode 4 - pushq %rbp - pushq %r14 - pushq %rbx - - movl %edi, %ebx - callq bar - movl %eax, %r14d - - imull $17, %ebx, %ebp -# This imull is 3 bytes long and should have started at 0xe, so two bytes -# of nop padding are inserted instead and it starts at 0x10 -# CHECK: nop -# CHECK-NEXT: 10: imull - - movl %ebx, %edi - callq bar - cmpl %r14d, %ebp -# CHECK-RELAX: nopl - jle .L_ELSE -# Due to the padding that's inserted before the addl, the jump target -# becomes farther by one byte. -# CHECK-OPT: jle 0x24 -# CHECK-RELAX: jle 0x2d - - addl %ebp, %eax -# CHECK-OPT: nop -# CHECK-OPT-NEXT:20: addl -# CHECK-RELAX: 26: addl - - jmp .L_RET -.L_ELSE: - imull %ebx, %eax -.L_RET: - ret - -# Just verifying that data fills don't drive bundling crazy - .data - .byte 40 - .byte 98 - - diff --git a/llvm/test/MC/X86/AlignedBundling/switch-section-locked-error.s b/llvm/test/MC/X86/AlignedBundling/switch-section-locked-error.s deleted file mode 100644 index 6ea3c36beb1cc..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/switch-section-locked-error.s +++ /dev/null @@ -1,16 +0,0 @@ -# RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s - -# This test invokes .bundle_lock and then switches to a different section -# w/o the appropriate unlock. - -# CHECK: ERROR: Unterminated .bundle_lock - - .bundle_align_mode 3 - .section text1, "x" - imull $17, %ebx, %ebp - .bundle_lock - imull $17, %ebx, %ebp - - .section text2, "x" - imull $17, %ebx, %ebp - diff --git a/llvm/test/MC/X86/AlignedBundling/unlock-without-lock-error.s b/llvm/test/MC/X86/AlignedBundling/unlock-without-lock-error.s deleted file mode 100644 index 811ef95a451d4..0000000000000 --- a/llvm/test/MC/X86/AlignedBundling/unlock-without-lock-error.s +++ /dev/null @@ -1,11 +0,0 @@ -# RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s - -# .bundle_unlock can't come without a .bundle_lock before it - -# CHECK: ERROR: .bundle_unlock without matching lock - - .bundle_align_mode 3 - imull $17, %ebx, %ebp - .bundle_unlock - - diff --git a/llvm/test/MC/X86/align-branch-bundle.s b/llvm/test/MC/X86/align-branch-bundle.s deleted file mode 100644 index aba90f02a8a69..0000000000000 --- a/llvm/test/MC/X86/align-branch-bundle.s +++ /dev/null @@ -1,21 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown --x86-align-branch-boundary=16 --x86-align-branch=fused+jcc --mc-relax-all %s | llvm-objdump --no-print-imm-hex -d --no-show-raw-insn - | FileCheck %s - -# Check using option --x86-align-branch-boundary=16 --x86-align-branch=fused+jcc --mc-relax-all with bundle won't make code crazy - -# CHECK: 0: pushq %rbp -# CHECK-NEXT: 1: testq $2, %rdx -# CHECK-NEXT: 8: jne -# CHECK-NEXT: e: nop -# CHECK-NEXT: 10: jle - - .text - .p2align 4 -foo: - push %rbp - # Will be bundle-aligning to 8 byte boundaries - .bundle_align_mode 3 - test $2, %rdx - jne foo -# This jle is 6 bytes long and should have started at 0xe, so two bytes -# of nop padding are inserted instead and it starts at 0x10 - jle foo From 496fd25eba5cabe8749175fd5ad46fa540faf402 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Thu, 17 Jul 2025 15:27:49 -0700 Subject: [PATCH 02/39] [MCCAS] remove `writeFragmentPadding` references Delete usage of `writeFragmentPadding` that is removed from upstream. rdar://156089370 --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index e35dcf9985c4f..0d4861d4a5f94 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -1781,7 +1781,6 @@ MCSymbolIdFragmentRef::materialize(MCCASReader &Reader, Expected B = Builder::startNode(MB.Schema, KindString); \ if (!B) \ return B.takeError(); \ - MB.Asm.writeFragmentPadding(MB.FragmentOS, F, FragmentSize); \ B->Data.append(MB.FragmentData); \ B->Data.append(FragmentContents.begin(), FragmentContents.end()); \ assert( \ @@ -1974,8 +1973,6 @@ Error MCDataFragmentMerger::emitMergedFragments() { switch (Candidate.first->getKind()) { #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ case MCFragment::MCEnumName: { \ - const MCFragmentName *SF = cast(Candidate.first); \ - Builder.Asm.writeFragmentPadding(FragmentOS, *SF, Candidate.second); \ FragmentData.append(CandidateContents); \ break; \ } From 2c92989efac11a1894ccb588665b7667ae3df95b Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 15 Jul 2025 21:56:55 -0700 Subject: [PATCH 03/39] MC: Restructure MCFragment as a fixed part and a variable tail Refactor the fragment representation of `push rax; jmp foo; nop; jmp foo`, previously encoded as `MCDataFragment(nop); MCRelaxableFragment(jmp foo); MCDataFragment(nop); MCRelaxableFragment(jmp foo)`, to ``` MCFragment(fixed: push rax, variable: jmp foo) MCFragment(fixed: nop, variable: jmp foo) ``` Changes: * Eliminate MCEncodedFragment, moving content and fixup storage to MCFragment. * The new MCFragment contains a fixed-size content (similar to previous MCDataFragment) and an optional variable-size tail. * The variable-size tail supports FT_Relaxable, FT_LEB, FT_Dwarf, and FT_DwarfFrame, with plans to extend to other fragment types. dyn_cast/isa should be avoided for the converted fragment subclasses. * In `setVarFixups`, source fixup offsets are relative to the variable part's start. Stored fixup (in `FixupStorage`) offsets are relative to the fixed part's start. A lot of code does `getFragmentOffset(Frag) + Fixup.getOffset()`, expecting the fixup offset to be relative to the fixed part's start. * HexagonAsmBackend::fixupNeedsRelaxationAdvanced needs to know the associated instruction for a fixup. We have to add a `const MCFragment &` parameter. * In MCObjectStreamer, extend `absoluteSymbolDiff` to apply to FT_Relaxable as otherwise there would be many more FT_DwarfFrame fragments in -g compilations. https://llvm-compile-time-tracker.com/compare.php?from=28e1473e8e523150914e8c7ea50b44fb0d2a8d65&to=778d68ad1d48e7f111ea853dd249912c601bee89&stat=instructions:u ``` stage2-O0-g instructins:u geomeon (-0.07%) stage1-ReleaseLTO-g (link only) max-rss geomean (-0.39%) ``` ``` % /t/clang-old -g -c sqlite3.i -w -mllvm -debug-only=mc-dump &| awk '/^[0-9]+/{s[$2]++;tot++} END{print "Total",tot; n=asorti(s, si); for(i=1;i<=n;i++) print si[i],s[si[i]]}' Total 59675 Align 2215 Data 29700 Dwarf 12044 DwarfCallFrame 4216 Fill 92 LEB 12 Relaxable 11396 % /t/clang-new -g -c sqlite3.i -w -mllvm -debug-only=mc-dump &| awk '/^[0-9]+/{s[$2]++;tot++} END{print "Total",tot; n=asorti(s, si); for(i=1;i<=n;i++) print si[i],s[si[i]]}' Total 32287 Align 2215 Data 2312 Dwarf 12044 DwarfCallFrame 4216 Fill 92 LEB 12 Relaxable 11396 ``` Pull Request: https://github.com/llvm/llvm-project/pull/148544 --- llvm/include/llvm/MC/MCAsmBackend.h | 18 +- llvm/include/llvm/MC/MCAssembler.h | 15 +- llvm/include/llvm/MC/MCCodeView.h | 3 +- llvm/include/llvm/MC/MCContext.h | 3 +- llvm/include/llvm/MC/MCELFStreamer.h | 3 +- llvm/include/llvm/MC/MCObjectStreamer.h | 10 +- llvm/include/llvm/MC/MCSection.h | 290 +++++++++--------- llvm/include/llvm/MC/MCWasmStreamer.h | 2 +- llvm/lib/MC/MCAsmBackend.cpp | 9 +- llvm/lib/MC/MCAssembler.cpp | 116 +++---- llvm/lib/MC/MCCodeView.cpp | 2 +- llvm/lib/MC/MCContext.cpp | 6 +- llvm/lib/MC/MCELFStreamer.cpp | 2 +- llvm/lib/MC/MCExpr.cpp | 10 +- llvm/lib/MC/MCFragment.cpp | 88 +++--- llvm/lib/MC/MCMachOStreamer.cpp | 7 +- llvm/lib/MC/MCObjectStreamer.cpp | 91 +++--- llvm/lib/MC/MCSection.cpp | 34 +- llvm/lib/MC/MCSymbol.cpp | 2 +- llvm/lib/MC/MCWasmStreamer.cpp | 2 +- llvm/lib/MC/MCWin64EH.cpp | 2 +- llvm/lib/MC/MCWinCOFFStreamer.cpp | 10 +- llvm/lib/MC/MCXCOFFStreamer.cpp | 2 +- llvm/lib/MC/MachObjectWriter.cpp | 2 +- llvm/lib/MC/WasmObjectWriter.cpp | 10 +- llvm/lib/MC/WinCOFFObjectWriter.cpp | 4 +- .../MCTargetDesc/AArch64ELFStreamer.cpp | 8 +- .../Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 3 +- .../Target/ARM/MCTargetDesc/ARMAsmBackend.h | 3 +- .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 11 +- .../CSKY/MCTargetDesc/CSKYAsmBackend.cpp | 3 +- .../Target/CSKY/MCTargetDesc/CSKYAsmBackend.h | 3 +- .../MCTargetDesc/HexagonAsmBackend.cpp | 15 +- .../MCTargetDesc/LoongArchAsmBackend.cpp | 37 ++- .../MCTargetDesc/LoongArchAsmBackend.h | 8 +- .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 45 ++- .../RISCV/MCTargetDesc/RISCVAsmBackend.h | 11 +- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 58 ++-- llvm/test/MC/ELF/mc-dump.s | 22 +- 39 files changed, 511 insertions(+), 459 deletions(-) diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index cd7c4b79b594b..09cc367837117 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -22,11 +22,8 @@ namespace llvm { class MCAlignFragment; -class MCDwarfCallFrameFragment; -class MCDwarfLineAddrFragment; class MCFragment; class MCLEBFragment; -class MCRelaxableFragment; class MCSymbol; class MCAssembler; class MCContext; @@ -175,8 +172,9 @@ class LLVM_ABI MCAsmBackend { /// Target specific predicate for whether a given fixup requires the /// associated instruction to be relaxed. - virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, - uint64_t, bool Resolved) const; + virtual bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, + bool Resolved) const; /// Simple predicate for targets where !Resolved implies requiring relaxation virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, @@ -197,18 +195,16 @@ class LLVM_ABI MCAsmBackend { } // Defined by linker relaxation targets. - virtual bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, - bool &WasRelaxed) const { + virtual bool relaxDwarfLineAddr(MCFragment &, bool &WasRelaxed) const { return false; } - virtual bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const { + virtual bool relaxDwarfCFA(MCFragment &, bool &WasRelaxed) const { return false; } // Defined by linker relaxation targets to possibly emit LEB128 relocations // and set Value at the relocated location. - virtual std::pair relaxLEB128(MCLEBFragment &LF, + virtual std::pair relaxLEB128(MCFragment &, int64_t &Value) const { return std::make_pair(false, false); } @@ -246,7 +242,7 @@ class LLVM_ABI MCAsmBackend { bool isDarwinCanonicalPersonality(const MCSymbol *Sym) const; - // Return STI for fragments of type MCRelaxableFragment and MCDataFragment + // Return STI for fragments of type MCRelaxableFragment and MCFragment // with hasInstructions() == true. static const MCSubtargetInfo *getSubtargetInfo(const MCFragment &F); }; diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 6b0d1b202e8c2..aa396efa9f018 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -34,13 +34,10 @@ namespace llvm { class MCBoundaryAlignFragment; class MCCVDefRangeFragment; class MCCVInlineLineTableFragment; -class MCDwarfCallFrameFragment; -class MCDwarfLineAddrFragment; -class MCEncodedFragment; +class MCFragment; class MCFixup; class MCLEBFragment; class MCPseudoProbeAddrFragment; -class MCRelaxableFragment; class MCSymbolRefExpr; class raw_ostream; class MCAsmBackend; @@ -102,7 +99,7 @@ class MCAssembler { /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). - bool fixupNeedsRelaxation(const MCRelaxableFragment &, const MCFixup &) const; + bool fixupNeedsRelaxation(const MCFragment &, const MCFixup &) const; void layoutSection(MCSection &Sec); /// Perform one layout iteration and return the index of the first stable @@ -111,11 +108,11 @@ class MCAssembler { /// Perform relaxation on a single fragment. bool relaxFragment(MCFragment &F); - bool relaxInstruction(MCRelaxableFragment &IF); - bool relaxLEB(MCLEBFragment &IF); + bool relaxInstruction(MCFragment &F); + bool relaxLEB(MCFragment &F); bool relaxBoundaryAlign(MCBoundaryAlignFragment &BF); - bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF); - bool relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF); + bool relaxDwarfLineAddr(MCFragment &F); + bool relaxDwarfCallFrameFragment(MCFragment &F); bool relaxCVInlineLineTable(MCCVInlineLineTableFragment &DF); bool relaxCVDefRange(MCCVDefRangeFragment &DF); bool relaxFill(MCFillFragment &F); diff --git a/llvm/include/llvm/MC/MCCodeView.h b/llvm/include/llvm/MC/MCCodeView.h index 88f84a2462841..9cde44c71baff 100644 --- a/llvm/include/llvm/MC/MCCodeView.h +++ b/llvm/include/llvm/MC/MCCodeView.h @@ -26,7 +26,6 @@ namespace llvm { class MCAssembler; class MCCVDefRangeFragment; class MCCVInlineLineTableFragment; -class MCDataFragment; class MCFragment; class MCSection; class MCSymbol; @@ -231,7 +230,7 @@ class CodeViewContext { StringMap StringTable; /// The fragment that ultimately holds our strings. - MCDataFragment *StrTabFragment = nullptr; + MCFragment *StrTabFragment = nullptr; SmallVector StrTab = {'\0'}; /// Get a string table offset. diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 5a8ec17dae1cc..c137f6184a9a7 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -47,7 +47,6 @@ namespace llvm { class CodeViewContext; class MCAsmInfo; -class MCDataFragment; class MCInst; class MCLabel; class MCObjectFileInfo; @@ -334,7 +333,7 @@ class MCContext { void reportCommon(SMLoc Loc, std::function); - MCDataFragment *allocInitialFragment(MCSection &Sec); + MCFragment *allocInitialFragment(MCSection &Sec); MCSymbolTableEntry &getSymbolTableEntry(StringRef Name); diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h index cf931e99acce1..ad0961c8bcf97 100644 --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -17,7 +17,6 @@ namespace llvm { class ELFObjectWriter; class MCContext; -class MCDataFragment; class MCFragment; class MCObjectWriter; class MCSection; @@ -51,7 +50,7 @@ class MCELFStreamer : public MCObjectStreamer { void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override; void changeSection(MCSection *Section, uint32_t Subsection = 0) override; void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F, + void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment &F, uint64_t Offset) override; void emitWeakReference(MCSymbol *Alias, const MCSymbol *Target) override; bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 5990d70a076f5..e2a77b809b6ca 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -43,8 +43,8 @@ class MCObjectStreamer : public MCStreamer { struct PendingMCFixup { const MCSymbol *Sym; MCFixup Fixup; - MCDataFragment *DF; - PendingMCFixup(const MCSymbol *McSym, MCDataFragment *F, MCFixup McFixup) + MCFragment *DF; + PendingMCFixup(const MCSymbol *McSym, MCFragment *F, MCFixup McFixup) : Sym(McSym), Fixup(McFixup), DF(F) {} }; SmallVector PendingFixups; @@ -92,10 +92,10 @@ class MCObjectStreamer : public MCStreamer { } /// Get a data fragment to write into, creating a new one if the current - /// fragment is not a data fragment. + /// fragment is not FT_Data. /// Optionally a \p STI can be passed in so that a new fragment is created /// if the Subtarget differs from the current fragment. - MCDataFragment *getOrCreateDataFragment(const MCSubtargetInfo* STI = nullptr); + MCFragment *getOrCreateDataFragment(const MCSubtargetInfo *STI = nullptr); protected: bool changeSectionImpl(MCSection *Section, uint32_t Subsection); @@ -109,7 +109,7 @@ class MCObjectStreamer : public MCStreamer { /// @{ void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - virtual void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F, + virtual void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment &F, uint64_t Offset); void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void emitConditionalAssignment(MCSymbol *Symbol, diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 6c8fe1a8062f5..362893c5e4361 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -46,8 +46,6 @@ class LLVM_ABI MCSection { friend MCAssembler; friend MCObjectStreamer; friend class MCFragment; - friend class MCEncodedFragment; - friend class MCRelaxableFragment; static constexpr unsigned NonUniqueID = ~0U; enum SectionVariant { @@ -237,54 +235,50 @@ class MCFragment { /// MCRelaxableFragment: x86-specific bool AllowAutoPadding : 1; - LLVM_ABI MCFragment(FragmentType Kind, bool HasInstructions); - -public: - MCFragment() = delete; - MCFragment(const MCFragment &) = delete; - MCFragment &operator=(const MCFragment &) = delete; - - MCFragment *getNext() const { return Next; } - - FragmentType getKind() const { return Kind; } - - MCSection *getParent() const { return Parent; } - void setParent(MCSection *Value) { Parent = Value; } - - LLVM_ABI const MCSymbol *getAtom() const; - - unsigned getLayoutOrder() const { return LayoutOrder; } - void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } - - /// Does this fragment have instructions emitted into it? By default - /// this is false, but specific fragment types may set it to true. - bool hasInstructions() const { return HasInstructions; } - - bool isLinkerRelaxable() const { return LinkerRelaxable; } - void setLinkerRelaxable() { LinkerRelaxable = true; } - - LLVM_ABI void dump() const; -}; - -/// Interface implemented by fragments that contain encoded instructions and/or -/// data. -class MCEncodedFragment : public MCFragment { uint32_t ContentStart = 0; uint32_t ContentEnd = 0; uint32_t FixupStart = 0; uint32_t FixupEnd = 0; -protected: - MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions) - : MCFragment(FType, HasInstructions) {} + uint32_t VarContentStart = 0; + uint32_t VarContentEnd = 0; + uint32_t VarFixupStart = 0; + uint32_t VarFixupEnd = 0; - /// The MCSubtargetInfo in effect when the instruction was encoded. - /// It must be non-null for instructions. const MCSubtargetInfo *STI = nullptr; + // Optional variable-size tail used by various fragment types. + union Tail { + struct { + uint32_t Opcode; + uint32_t Flags; + uint32_t OperandStart; + uint32_t OperandSize; + } relax; + struct { + // True if this is a sleb128, false if uleb128. + bool IsSigned; + // The value this fragment should contain. + const MCExpr *Value; + } leb; + // Used by .debug_frame and .debug_line to encode an address difference. + struct { + // The address difference between two labels. + const MCExpr *AddrDelta; + // The value of the difference between the two line numbers between two + // .loc dwarf directives. + int64_t LineDelta; + } dwarf; + } u{}; + public: - static bool classof(const MCFragment *F) { - MCFragment::FragmentType Kind = F->getKind(); + LLVM_ABI MCFragment(FragmentType Kind = MCFragment::FT_Data, + bool HasInstructions = false); + MCFragment(const MCFragment &) = delete; + MCFragment &operator=(const MCFragment &) = delete; + + bool isEncoded() const { + MCFragment::FragmentType Kind = getKind(); switch (Kind) { default: return false; @@ -300,6 +294,24 @@ class MCEncodedFragment : public MCFragment { } } + MCFragment *getNext() const { return Next; } + + FragmentType getKind() const { return Kind; } + + MCSection *getParent() const { return Parent; } + void setParent(MCSection *Value) { Parent = Value; } + + LLVM_ABI const MCSymbol *getAtom() const; + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + /// Does this fragment have instructions emitted into it? By default + /// this is false, but specific fragment types may set it to true. + bool hasInstructions() const { return HasInstructions; } + + LLVM_ABI void dump() const; + /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. /// Guaranteed to be non-null if hasInstructions() == true const MCSubtargetInfo *getSubtargetInfo() const { return STI; } @@ -311,6 +323,9 @@ class MCEncodedFragment : public MCFragment { this->STI = &STI; } + bool isLinkerRelaxable() const { return LinkerRelaxable; } + void setLinkerRelaxable() { LinkerRelaxable = true; } + bool getAllowAutoPadding() const { return AllowAutoPadding; } void setAllowAutoPadding(bool V) { AllowAutoPadding = V; } @@ -350,7 +365,24 @@ class MCEncodedFragment : public MCFragment { .slice(ContentStart, ContentEnd - ContentStart); } - // Fixup-related functions manage parent's storage using FixupStart and + void setVarContents(ArrayRef Contents); + void clearVarContents() { setVarContents({}); } + MutableArrayRef getVarContents() { + return MutableArrayRef(getParent()->ContentStorage) + .slice(VarContentStart, VarContentEnd - VarContentStart); + } + ArrayRef getVarContents() const { + return ArrayRef(getParent()->ContentStorage) + .slice(VarContentStart, VarContentEnd - VarContentStart); + } + + size_t getFixedSize() const { return ContentEnd - ContentStart; } + size_t getVarSize() const { return VarContentEnd - VarContentStart; } + size_t getSize() const { + return ContentEnd - ContentStart + (VarContentEnd - VarContentStart); + } + + //== Fixup-related functions manage parent's storage using FixupStart and // FixupSize. void clearFixups() { FixupEnd = FixupStart; } LLVM_ABI void addFixup(MCFixup Fixup); @@ -365,65 +397,100 @@ class MCEncodedFragment : public MCFragment { .slice(FixupStart, FixupEnd - FixupStart); } - size_t getSize() const { return ContentEnd - ContentStart; } -}; - -/// Fragment for data and encoded instructions. -/// -class MCDataFragment : public MCEncodedFragment { -public: - MCDataFragment() : MCEncodedFragment(FT_Data, false) {} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Data; + // Source fixup offsets are relative to the variable part's start. + // Stored fixup offsets are relative to the fixed part's start. + void setVarFixups(ArrayRef Fixups); + void clearVarFixups() { setVarFixups({}); } + MutableArrayRef getVarFixups() { + return MutableArrayRef(getParent()->FixupStorage) + .slice(VarFixupStart, VarFixupEnd - VarFixupStart); } -}; - -/// A relaxable fragment holds on to its MCInst, since it may need to be -/// relaxed during the assembler layout and relaxation stage. -/// -class MCRelaxableFragment : public MCEncodedFragment { - uint32_t Opcode = 0; - uint32_t Flags = 0; - uint32_t OperandStart = 0; - uint32_t OperandSize = 0; - -public: - MCRelaxableFragment(const MCSubtargetInfo &STI) - : MCEncodedFragment(FT_Relaxable, true) { - this->STI = &STI; + ArrayRef getVarFixups() const { + return ArrayRef(getParent()->FixupStorage) + .slice(VarFixupStart, VarFixupEnd - VarFixupStart); } - unsigned getOpcode() const { return Opcode; } + //== FT_Relaxable functions + unsigned getOpcode() const { + assert(Kind == FT_Relaxable); + return u.relax.Opcode; + } ArrayRef getOperands() const { + assert(Kind == FT_Relaxable); return MutableArrayRef(getParent()->MCOperandStorage) - .slice(OperandStart, OperandSize); + .slice(u.relax.OperandStart, u.relax.OperandSize); } MCInst getInst() const { + assert(Kind == FT_Relaxable); MCInst Inst; - Inst.setOpcode(Opcode); - Inst.setFlags(Flags); + Inst.setOpcode(u.relax.Opcode); + Inst.setFlags(u.relax.Flags); Inst.setOperands(ArrayRef(getParent()->MCOperandStorage) - .slice(OperandStart, OperandSize)); + .slice(u.relax.OperandStart, u.relax.OperandSize)); return Inst; } void setInst(const MCInst &Inst) { - Opcode = Inst.getOpcode(); - Flags = Inst.getFlags(); + assert(Kind == FT_Relaxable); + u.relax.Opcode = Inst.getOpcode(); + u.relax.Flags = Inst.getFlags(); auto &S = getParent()->MCOperandStorage; - if (Inst.getNumOperands() > OperandSize) { - OperandStart = S.size(); + if (Inst.getNumOperands() > u.relax.OperandSize) { + u.relax.OperandStart = S.size(); S.resize_for_overwrite(S.size() + Inst.getNumOperands()); } - OperandSize = Inst.getNumOperands(); - llvm::copy(Inst, S.begin() + OperandStart); + u.relax.OperandSize = Inst.getNumOperands(); + llvm::copy(Inst, S.begin() + u.relax.OperandStart); } - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Relaxable; + //== FT_LEB functions + const MCExpr &getLEBValue() const { + assert(Kind == FT_LEB); + return *u.leb.Value; + } + void setLEBValue(const MCExpr *Expr) { + assert(Kind == FT_LEB); + u.leb.Value = Expr; + } + bool isLEBSigned() const { + assert(Kind == FT_LEB); + return u.leb.IsSigned; + } + void setLEBSigned(bool S) { + assert(Kind == FT_LEB); + u.leb.IsSigned = S; } + + //== FT_DwarfFrame functions + const MCExpr &getDwarfAddrDelta() const { + assert(Kind == FT_Dwarf || Kind == FT_DwarfFrame); + return *u.dwarf.AddrDelta; + } + void setDwarfAddrDelta(const MCExpr *E) { + assert(Kind == FT_Dwarf || Kind == FT_DwarfFrame); + u.dwarf.AddrDelta = E; + } + int64_t getDwarfLineDelta() const { + assert(Kind == FT_Dwarf); + return u.dwarf.LineDelta; + } + void setDwarfLineDelta(int64_t LineDelta) { + assert(Kind == FT_Dwarf); + u.dwarf.LineDelta = LineDelta; + } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data. +class MCEncodedFragment : public MCFragment { +protected: + MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions) + : MCFragment(FType, HasInstructions) {} }; +// TODO Delete +using MCDataFragment = MCFragment; +using MCRelaxableFragment = MCFragment; + class MCAlignFragment : public MCFragment { /// Flag to indicate that (optimal) NOPs should be emitted instead /// of using the provided value. The exact interpretation of this flag is @@ -555,67 +622,6 @@ class MCOrgFragment : public MCFragment { } }; -class MCLEBFragment final : public MCEncodedFragment { - /// True if this is a sleb128, false if uleb128. - bool IsSigned; - - /// The value this fragment should contain. - const MCExpr *Value; - -public: - MCLEBFragment(const MCExpr &Value, bool IsSigned) - : MCEncodedFragment(FT_LEB, false), IsSigned(IsSigned), Value(&Value) {} - - const MCExpr &getValue() const { return *Value; } - void setValue(const MCExpr *Expr) { Value = Expr; } - - bool isSigned() const { return IsSigned; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_LEB; - } -}; - -class MCDwarfLineAddrFragment : public MCEncodedFragment { - /// The value of the difference between the two line numbers - /// between two .loc dwarf directives. - int64_t LineDelta; - - /// The expression for the difference of the two symbols that - /// make up the address delta between two .loc dwarf directives. - const MCExpr *AddrDelta; - -public: - MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta) - : MCEncodedFragment(FT_Dwarf, false), LineDelta(LineDelta), - AddrDelta(&AddrDelta) {} - - int64_t getLineDelta() const { return LineDelta; } - - const MCExpr &getAddrDelta() const { return *AddrDelta; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Dwarf; - } -}; - -class MCDwarfCallFrameFragment : public MCEncodedFragment { - /// The expression for the difference of the two symbols that - /// make up the address delta between two .cfi_* dwarf directives. - const MCExpr *AddrDelta; - -public: - MCDwarfCallFrameFragment(const MCExpr &AddrDelta) - : MCEncodedFragment(FT_DwarfFrame, false), AddrDelta(&AddrDelta) {} - - const MCExpr &getAddrDelta() const { return *AddrDelta; } - void setAddrDelta(const MCExpr *E) { AddrDelta = E; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_DwarfFrame; - } -}; - /// Represents a symbol table index fragment. class MCSymbolIdFragment : public MCFragment { const MCSymbol *Sym; diff --git a/llvm/include/llvm/MC/MCWasmStreamer.h b/llvm/include/llvm/MC/MCWasmStreamer.h index 2598c261ea02a..e8a71975c5d62 100644 --- a/llvm/include/llvm/MC/MCWasmStreamer.h +++ b/llvm/include/llvm/MC/MCWasmStreamer.h @@ -42,7 +42,7 @@ class MCWasmStreamer : public MCObjectStreamer { void changeSection(MCSection *Section, uint32_t Subsection) override; void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F, + void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment &F, uint64_t Offset) override; bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, diff --git a/llvm/lib/MC/MCAsmBackend.cpp b/llvm/lib/MC/MCAsmBackend.cpp index b55907254fb2d..6579a59b3af0c 100644 --- a/llvm/lib/MC/MCAsmBackend.cpp +++ b/llvm/lib/MC/MCAsmBackend.cpp @@ -132,7 +132,8 @@ MCFixupKindInfo MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { return Builtins[Kind - FK_NONE]; } -bool MCAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool MCAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &, uint64_t Value, bool Resolved) const { if (!Resolved) @@ -165,9 +166,7 @@ bool MCAsmBackend::isDarwinCanonicalPersonality(const MCSymbol *Sym) const { const MCSubtargetInfo *MCAsmBackend::getSubtargetInfo(const MCFragment &F) { const MCSubtargetInfo *STI = nullptr; - if (auto *DF = dyn_cast(&F)) { - STI = DF->getSubtargetInfo(); - assert(!DF->hasInstructions() || STI != nullptr); - } + STI = F.getSubtargetInfo(); + assert(!F.hasInstructions() || STI != nullptr); return STI; } diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 7f01e272a323e..77741a60d0408 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -202,7 +202,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const { case MCFragment::FT_CVInlineLines: case MCFragment::FT_CVDefRange: case MCFragment::FT_PseudoProbe: - return cast(F).getContents().size(); + return F.getSize(); case MCFragment::FT_Fill: { auto &FF = cast(F); int64_t NumValues = 0; @@ -426,8 +426,9 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, ++stats::EmittedDataFragments; else if (F.getKind() == MCFragment::FT_Relaxable) ++stats::EmittedRelaxableFragments; - const auto &EF = cast(F); + const auto &EF = cast(F); OS << StringRef(EF.getContents().data(), EF.getContents().size()); + OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size()); break; } case MCFragment::FT_Align: { @@ -592,11 +593,10 @@ void MCAssembler::writeSectionData(raw_ostream &OS, // Check that we aren't trying to write a non-zero contents (or fixups) // into a virtual section. This is to support clients which use standard // directives to fill the contents of virtual sections. - const MCDataFragment &DF = cast(F); - if (DF.getFixups().size()) + if (F.getFixups().size() || F.getVarFixups().size()) reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + Sec->getName() + "' cannot have fixups"); - for (char C : DF.getContents()) + for (char C : F.getContents()) if (C) { reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + Sec->getName() + @@ -649,7 +649,7 @@ void MCAssembler::layout() { // Chain together fragments from all subsections. if (Sec.Subsections.size() > 1) { - MCDataFragment Dummy; + MCFragment Dummy; MCFragment *Tail = &Dummy; for (auto &[_, List] : Sec.Subsections) { assert(List.Head); @@ -697,17 +697,28 @@ void MCAssembler::layout() { // Evaluate and apply the fixups, generating relocation entries as necessary. for (MCSection &Sec : *this) { - for (MCFragment &Frag : Sec) { + for (MCFragment &F : Sec) { // Process fragments with fixups here. - if (auto *F = dyn_cast(&Frag)) { - auto Contents = F->getContents(); - for (MCFixup &Fixup : F->getFixups()) { + if (F.isEncoded()) { + auto Contents = F.getContents(); + for (MCFixup &Fixup : F.getFixups()) { uint64_t FixedValue; MCValue Target; - evaluateFixup(Frag, Fixup, Target, FixedValue, + evaluateFixup(F, Fixup, Target, FixedValue, /*RecordReloc=*/true, Contents); } - } else if (auto *AF = dyn_cast(&Frag)) { + // In the variable part, fixup offsets are relative to the fixed part's + // start. Extend the variable contents to the left to account for the + // fixed part size. + Contents = MutableArrayRef(F.getParent()->ContentStorage) + .slice(F.VarContentStart - Contents.size(), F.getSize()); + for (MCFixup &Fixup : F.getVarFixups()) { + uint64_t FixedValue; + MCValue Target; + evaluateFixup(F, Fixup, Target, FixedValue, + /*RecordReloc=*/true, Contents); + } + } else if (auto *AF = dyn_cast(&F)) { // For RISC-V linker relaxation, an alignment relocation might be // needed. if (AF->hasEmitNops()) @@ -727,18 +738,18 @@ void MCAssembler::Finish() { assert(PendingErrors.empty()); } -bool MCAssembler::fixupNeedsRelaxation(const MCRelaxableFragment &F, +bool MCAssembler::fixupNeedsRelaxation(const MCFragment &F, const MCFixup &Fixup) const { assert(getBackendPtr() && "Expected assembler backend"); MCValue Target; uint64_t Value; bool Resolved = evaluateFixup(F, const_cast(Fixup), Target, Value, /*RecordReloc=*/false, {}); - return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Target, Value, + return getBackend().fixupNeedsRelaxationAdvanced(F, Fixup, Target, Value, Resolved); } -bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { +bool MCAssembler::relaxInstruction(MCFragment &F) { assert(getEmitterPtr() && "Expected CodeEmitter defined for relaxInstruction"); // If this inst doesn't ever need relaxation, ignore it. This occurs when we @@ -749,7 +760,7 @@ bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { return false; bool DoRelax = false; - for (const MCFixup &Fixup : F.getFixups()) + for (const MCFixup &Fixup : F.getVarFixups()) if ((DoRelax = fixupNeedsRelaxation(F, Fixup))) break; if (!DoRelax) @@ -757,7 +768,7 @@ bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { ++stats::RelaxedInstructions; - // TODO Refactor relaxInstruction to accept MCRelaxableFragment and remove + // TODO Refactor relaxInstruction to accept MCFragment and remove // `setInst`. MCInst Relaxed = F.getInst(); getBackend().relaxInstruction(Relaxed, *F.getSubtargetInfo()); @@ -767,30 +778,30 @@ bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { SmallVector Data; SmallVector Fixups; getEmitter().encodeInstruction(Relaxed, Data, Fixups, *F.getSubtargetInfo()); - F.setContents(Data); - F.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); return true; } -bool MCAssembler::relaxLEB(MCLEBFragment &LF) { - const unsigned OldSize = static_cast(LF.getContents().size()); +bool MCAssembler::relaxLEB(MCFragment &F) { + const unsigned OldSize = F.getVarSize(); unsigned PadTo = OldSize; int64_t Value; - LF.clearFixups(); + F.clearVarFixups(); // Use evaluateKnownAbsolute for Mach-O as a hack: .subsections_via_symbols // requires that .uleb128 A-B is foldable where A and B reside in different // fragments. This is used by __gcc_except_table. bool Abs = getWriter().getSubsectionsViaSymbols() - ? LF.getValue().evaluateKnownAbsolute(Value, *this) - : LF.getValue().evaluateAsAbsolute(Value, *this); + ? F.getLEBValue().evaluateKnownAbsolute(Value, *this) + : F.getLEBValue().evaluateAsAbsolute(Value, *this); if (!Abs) { bool Relaxed, UseZeroPad; - std::tie(Relaxed, UseZeroPad) = getBackend().relaxLEB128(LF, Value); + std::tie(Relaxed, UseZeroPad) = getBackend().relaxLEB128(F, Value); if (!Relaxed) { - reportError(LF.getValue().getLoc(), - Twine(LF.isSigned() ? ".s" : ".u") + + reportError(F.getLEBValue().getLoc(), + Twine(F.isLEBSigned() ? ".s" : ".u") + "leb128 expression is not absolute"); - LF.setValue(MCConstantExpr::create(0, Context)); + F.setLEBValue(MCConstantExpr::create(0, Context)); } uint8_t Tmp[10]; // maximum size: ceil(64/7) PadTo = std::max(PadTo, encodeULEB128(uint64_t(Value), Tmp)); @@ -803,11 +814,11 @@ bool MCAssembler::relaxLEB(MCLEBFragment &LF) { // without either adding padding to an LEB fragment or adding extra padding // to a later alignment fragment. To accommodate such tables, relaxation can // only increase an LEB fragment size here, not decrease it. See PR35809. - if (LF.isSigned()) + if (F.isLEBSigned()) Size = encodeSLEB128(Value, Data, PadTo); else Size = encodeULEB128(Value, Data, PadTo); - LF.setContents({reinterpret_cast(Data), Size}); + F.setVarContents({reinterpret_cast(Data), Size}); return OldSize != Size; } @@ -872,48 +883,45 @@ bool MCAssembler::relaxBoundaryAlign(MCBoundaryAlignFragment &BF) { return true; } -bool MCAssembler::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF) { +bool MCAssembler::relaxDwarfLineAddr(MCFragment &F) { bool WasRelaxed; - if (getBackend().relaxDwarfLineAddr(DF, WasRelaxed)) + if (getBackend().relaxDwarfLineAddr(F, WasRelaxed)) return WasRelaxed; MCContext &Context = getContext(); - auto OldSize = DF.getContents().size(); + auto OldSize = F.getVarSize(); int64_t AddrDelta; - bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, *this); + bool Abs = F.getDwarfAddrDelta().evaluateKnownAbsolute(AddrDelta, *this); assert(Abs && "We created a line delta with an invalid expression"); (void)Abs; - int64_t LineDelta; - LineDelta = DF.getLineDelta(); SmallVector Data; - - MCDwarfLineAddr::encode(Context, getDWARFLinetableParams(), LineDelta, - AddrDelta, Data); - DF.setContents(Data); - DF.clearFixups(); + MCDwarfLineAddr::encode(Context, getDWARFLinetableParams(), + F.getDwarfLineDelta(), AddrDelta, Data); + F.setVarContents(Data); + F.clearVarFixups(); return OldSize != Data.size(); } -bool MCAssembler::relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF) { +bool MCAssembler::relaxDwarfCallFrameFragment(MCFragment &F) { bool WasRelaxed; - if (getBackend().relaxDwarfCFA(DF, WasRelaxed)) + if (getBackend().relaxDwarfCFA(F, WasRelaxed)) return WasRelaxed; MCContext &Context = getContext(); int64_t Value; - bool Abs = DF.getAddrDelta().evaluateAsAbsolute(Value, *this); + bool Abs = F.getDwarfAddrDelta().evaluateAsAbsolute(Value, *this); if (!Abs) { - reportError(DF.getAddrDelta().getLoc(), + reportError(F.getDwarfAddrDelta().getLoc(), "invalid CFI advance_loc expression"); - DF.setAddrDelta(MCConstantExpr::create(0, Context)); + F.setDwarfAddrDelta(MCConstantExpr::create(0, Context)); return false; } - auto OldSize = DF.getContents().size(); + auto OldSize = F.getVarContents().size(); SmallVector Data; MCDwarfFrameEmitter::encodeAdvanceLoc(Context, Value, Data); - DF.setContents(Data); - DF.clearFixups(); + F.setVarContents(Data); + F.clearVarFixups(); return OldSize != Data.size(); } @@ -960,13 +968,13 @@ bool MCAssembler::relaxFragment(MCFragment &F) { case MCFragment::FT_Relaxable: assert(!getRelaxAll() && "Did not expect a MCRelaxableFragment in RelaxAll mode"); - return relaxInstruction(cast(F)); + return relaxInstruction(F); + case MCFragment::FT_LEB: + return relaxLEB(F); case MCFragment::FT_Dwarf: - return relaxDwarfLineAddr(cast(F)); + return relaxDwarfLineAddr(F); case MCFragment::FT_DwarfFrame: - return relaxDwarfCallFrameFragment(cast(F)); - case MCFragment::FT_LEB: - return relaxLEB(cast(F)); + return relaxDwarfCallFrameFragment(F); case MCFragment::FT_BoundaryAlign: return relaxBoundaryAlign(cast(F)); case MCFragment::FT_CVInlineLines: diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index 5d7914396e09f..1f9825185175a 100644 --- a/llvm/lib/MC/MCCodeView.cpp +++ b/llvm/lib/MC/MCCodeView.cpp @@ -166,7 +166,7 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) { // somewhere else. If somebody wants two string tables in their .s file, one // will just be empty. if (!StrTabFragment) { - StrTabFragment = Ctx.allocFragment(); + StrTabFragment = Ctx.allocFragment(); OS.insert(StrTabFragment); } diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 3e63038dc90ae..12b3fbab8fb8f 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -200,10 +200,10 @@ MCInst *MCContext::createMCInst() { return new (MCInstAllocator.Allocate()) MCInst; } -// Allocate the initial MCDataFragment for the begin symbol. -MCDataFragment *MCContext::allocInitialFragment(MCSection &Sec) { +// Allocate the initial MCFragment for the begin symbol. +MCFragment *MCContext::allocInitialFragment(MCSection &Sec) { assert(!Sec.curFragList()->Head); - auto *F = allocFragment(); + auto *F = allocFragment(); F->setParent(&Sec); Sec.curFragList()->Head = F; Sec.curFragList()->Tail = F; diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index ecc77c6705267..ffc57227cff16 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -68,7 +68,7 @@ void MCELFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { Symbol->setType(ELF::STT_TLS); } -void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F, +void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment &F, uint64_t Offset) { auto *Symbol = cast(S); MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset); diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index a196591744099..22dff497911de 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -324,7 +324,7 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, // symbols is limited to specific cases where the fragments between two // symbols (including the fragments the symbols are defined in) are // fixed-size fragments so the difference can be calculated. For example, - // this is important when the Subtarget is changed and a new MCDataFragment + // this is important when the Subtarget is changed and a new MCFragment // is created in the case of foo: instr; .arch_extension ext; instr .if . - // foo. if (SA.isVariable() || SB.isVariable()) @@ -352,7 +352,7 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, // the linker. bool BBeforeRelax = false, AAfterRelax = false; for (auto F = FB; F; F = F->getNext()) { - auto DF = dyn_cast(F); + auto DF = F->getKind() == MCFragment::FT_Data ? F : nullptr; if (DF && DF->isLinkerRelaxable()) { if (&*F != FB || SBOffset != DF->getContents().size()) BBeforeRelax = true; @@ -373,12 +373,12 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, unsigned Count; if (DF) { Displacement += DF->getContents().size(); - } else if (auto *RF = dyn_cast(F); - RF && Asm->hasFinalLayout()) { + } else if (F->getKind() == MCFragment::FT_Relaxable && + Asm->hasFinalLayout()) { // Before finishLayout, a relaxable fragment's size is indeterminate. // After layout, during relocation generation, it can be treated as a // data fragment. - Displacement += RF->getContents().size(); + Displacement += F->getSize(); } else if (auto *AF = dyn_cast(F); AF && Layout && AF->hasEmitNops() && !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign( diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index c62abac2793e4..49760a69a44cc 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -24,12 +24,15 @@ using namespace llvm; -static_assert(std::is_trivially_destructible_v, +static_assert(std::is_trivially_destructible_v, "fragment classes must be trivially destructible"); MCFragment::MCFragment(FragmentType Kind, bool HasInstructions) : Kind(Kind), HasInstructions(HasInstructions), LinkerRelaxable(false), - AllowAutoPadding(false) {} + AllowAutoPadding(false) { + static_assert(sizeof(MCFragment::Tail) <= 16, + "Keep the variable-size tail small"); +} const MCSymbol *MCFragment::getAtom() const { return cast(Parent)->getAtom(LayoutOrder); @@ -79,18 +82,56 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { OS << " Nops"; break; } - case MCFragment::FT_Data: { - const auto *F = cast(this); - if (F->isLinkerRelaxable()) + case MCFragment::FT_Data: + case MCFragment::FT_Relaxable: + case MCFragment::FT_LEB: + case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: { + if (isLinkerRelaxable()) OS << " LinkerRelaxable"; - auto Contents = F->getContents(); - OS << " Size:" << Contents.size() << " ["; - for (unsigned i = 0, e = Contents.size(); i != e; ++i) { + auto Fixed = getContents(); + auto Var = getVarContents(); + OS << " Size:" << Fixed.size(); + if (getKind() != MCFragment::FT_Data) + OS << '+' << Var.size(); + OS << " ["; + for (unsigned i = 0, e = Fixed.size(); i != e; ++i) { if (i) OS << ","; - OS << format("%02x", uint8_t(Contents[i])); + OS << format("%02x", uint8_t(Fixed[i])); + } + for (unsigned i = 0, e = Var.size(); i != e; ++i) { + if (Fixed.size() || i) + OS << ","; + OS << format("%02x", uint8_t(Var[i])); } OS << ']'; - printFixups(F->getFixups()); + switch (getKind()) { + case MCFragment::FT_Data: + break; + case MCFragment::FT_Relaxable: + OS << ' '; + getInst().dump_pretty(OS); + break; + case MCFragment::FT_LEB: { + OS << " Value:"; + getLEBValue().print(OS, nullptr); + OS << " Signed:" << isLEBSigned(); + break; + } + case MCFragment::FT_Dwarf: + OS << " AddrDelta:"; + getDwarfAddrDelta().print(OS, nullptr); + OS << " LineDelta:" << getDwarfLineDelta(); + break; + case MCFragment::FT_DwarfFrame: + OS << " AddrDelta:"; + getDwarfAddrDelta().print(OS, nullptr); + break; + default: + llvm_unreachable(""); + } + printFixups(getFixups()); + printFixups(getVarFixups()); break; } case MCFragment::FT_Fill: { @@ -107,13 +148,6 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { << " ControlledNopLength:" << NF->getControlledNopLength(); break; } - case MCFragment::FT_Relaxable: { - const auto *F = cast(this); - OS << " Size:" << F->getContents().size() << ' '; - F->getInst().dump_pretty(OS); - printFixups(F->getFixups()); - break; - } case MCFragment::FT_Org: { const auto *OF = cast(this); OS << " Offset:"; @@ -121,26 +155,6 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { OS << " Value:" << static_cast(OF->getValue()); break; } - case MCFragment::FT_Dwarf: { - const auto *OF = cast(this); - OS << " AddrDelta:"; - OF->getAddrDelta().print(OS, nullptr); - OS << " LineDelta:" << OF->getLineDelta(); - break; - } - case MCFragment::FT_DwarfFrame: { - const auto *CF = cast(this); - OS << " AddrDelta:"; - CF->getAddrDelta().print(OS, nullptr); - break; - } - case MCFragment::FT_LEB: { - const auto *LF = cast(this); - OS << " Value:"; - LF->getValue().print(OS, nullptr); - OS << " Signed:" << LF->isSigned(); - break; - } case MCFragment::FT_BoundaryAlign: { const auto *BF = cast(this); OS << " BoundarySize:" << BF->getAlignment().value() diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index 4ede2997a4455..13c1466d4d0ec 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -163,7 +163,7 @@ void MCMachOStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { // We have to create a new fragment if this is an atom defining symbol, // fragments cannot span atoms. if (cast(Symbol)->isSymbolLinkerVisible()) - insert(getContext().allocFragment()); + insert(getContext().allocFragment()); MCObjectStreamer::emitLabel(Symbol, Loc); @@ -491,8 +491,7 @@ void MCMachOStreamer::finalizeCGProfile() { // For each entry, reserve space for 2 32-bit indices and a 64-bit count. size_t SectionBytes = W.getCGProfile().size() * (2 * sizeof(uint32_t) + sizeof(uint64_t)); - cast(*CGProfileSection->begin()) - .appendContents(SectionBytes, 0); + (*CGProfileSection->begin()).appendContents(SectionBytes, 0); } MCStreamer *llvm::createMachOStreamer(MCContext &Context, @@ -521,7 +520,7 @@ void MCMachOStreamer::createAddrSigSection() { MCSection *AddrSigSection = Asm.getContext().getObjectFileInfo()->getAddrSigSection(); changeSection(AddrSigSection); - auto *Frag = cast(AddrSigSection->curFragList()->Head); + auto *Frag = cast(AddrSigSection->curFragList()->Head); // We will generate a series of pointer-sized symbol relocations at offset // 0x0. Set the section size to be large enough to contain a single pointer // (instead of emitting a zero-sized section) so these relocations are diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 4ab5e3e5d4b47..c0cef0f06c57a 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -66,8 +66,8 @@ void MCObjectStreamer::resolvePendingFixups() { // If the location symbol to relocate is in MCEncodedFragment, // put the Fixup into location symbol's fragment. Otherwise // put into PendingFixup.DF - MCFragment *SymFragment = PendingFixup.Sym->getFragment(); - if (auto *F = dyn_cast(SymFragment)) + MCFragment *F = PendingFixup.Sym->getFragment(); + if (F->isEncoded()) F->addFixup(PendingFixup.Fixup); else PendingFixup.DF->addFixup(PendingFixup.Fixup); @@ -76,7 +76,8 @@ void MCObjectStreamer::resolvePendingFixups() { } // As a compile-time optimization, avoid allocating and evaluating an MCExpr -// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment. +// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed +// part. static std::optional absoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo) { assert(Hi && Lo); @@ -85,8 +86,11 @@ static std::optional absoluteSymbolDiff(const MCSymbol *Hi, if (Hi->isVariable() || Lo->isVariable()) return std::nullopt; auto *LoF = Lo->getFragment(); - if (!LoF || LoF->getKind() != MCFragment::FT_Data || - Hi->getFragment() != LoF || LoF->isLinkerRelaxable()) + if (!LoF || Hi->getFragment() != LoF || LoF->isLinkerRelaxable()) + return std::nullopt; + // If either symbol resides in the variable part, bail out. + auto Fixed = LoF->getFixedSize(); + if (Lo->getOffset() > Fixed || Hi->getOffset() > Fixed) return std::nullopt; return Hi->getOffset() - Lo->getOffset(); @@ -131,7 +135,7 @@ void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) { MCDwarfFrameEmitter::Emit(*this, MAB, false); } -static bool canReuseDataFragment(const MCDataFragment &F, +static bool canReuseDataFragment(const MCFragment &F, const MCAssembler &Assembler, const MCSubtargetInfo *STI) { if (!F.hasInstructions()) @@ -146,11 +150,12 @@ static bool canReuseDataFragment(const MCDataFragment &F, return !STI || F.getSubtargetInfo() == STI; } -MCDataFragment * +MCFragment * MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) { - auto *F = dyn_cast(getCurrentFragment()); - if (!F || !canReuseDataFragment(*F, *Assembler, STI)) { - F = getContext().allocFragment(); + auto *F = getCurrentFragment(); + if (F->getKind() != MCFragment::FT_Data || + !canReuseDataFragment(*F, *Assembler, STI)) { + F = getContext().allocFragment(); insert(F); } return F; @@ -169,7 +174,7 @@ void MCObjectStreamer::emitCFISections(bool EH, bool Debug) { void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) { MCStreamer::emitValueImpl(Value, Size, Loc); - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); MCDwarfLineEntry::make(this, getCurrentSectionOnly()); @@ -218,7 +223,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { // If there is a current fragment, mark the symbol as pointing into it. // Otherwise queue the label and set its fragment pointer when we emit the // next fragment. - MCDataFragment *F = getOrCreateDataFragment(); + MCFragment *F = getOrCreateDataFragment(); Symbol->setFragment(F); Symbol->setOffset(F->getContents().size()); @@ -238,7 +243,7 @@ void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) { // Emit a label at a previously emitted fragment/offset position. This must be // within the currently-active section. void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, - MCDataFragment &F, uint64_t Offset) { + MCFragment &F, uint64_t Offset) { assert(F.getParent() == getCurrentSectionOnly()); MCStreamer::emitLabel(Symbol, Loc); getAssembler().registerSymbol(*Symbol); @@ -252,7 +257,10 @@ void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) { emitULEB128IntValue(IntValue); return; } - insert(getContext().allocFragment(*Value, false)); + auto *F = getOrCreateDataFragment(); + F->Kind = MCFragment::FT_LEB; + F->setLEBSigned(false); + F->setLEBValue(Value); } void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) { @@ -261,7 +269,10 @@ void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) { emitSLEB128IntValue(IntValue); return; } - insert(getContext().allocFragment(*Value, true)); + auto *F = getOrCreateDataFragment(); + F->Kind = MCFragment::FT_LEB; + F->setLEBSigned(true); + F->setLEBValue(Value); } void MCObjectStreamer::emitWeakReference(MCSymbol *Alias, @@ -285,7 +296,7 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section, // If the subsection number is not in the sorted Subsections list, create a // new fragment list. if (I == E || Subsections[I].first != Subsection) { - auto *F = getContext().allocFragment(); + auto *F = getContext().allocFragment(); F->setParent(Section); Subsections.insert(Subsections.begin() + I, {Subsection, MCSection::FragList{F, F}}); @@ -365,13 +376,12 @@ void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst, return; } - // Otherwise emit to a separate fragment. emitInstToFragment(Inst, STI); } void MCObjectStreamer::emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) { - MCDataFragment *F = getOrCreateDataFragment(&STI); + MCFragment *F = getOrCreateDataFragment(); // Append the instruction to the data fragment. size_t FixupStartIndex = F->getFixups().size(); @@ -396,18 +406,17 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst, void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &STI) { - // Always create a new, separate fragment here, because its size can change - // during relaxation. - MCRelaxableFragment *IF = - getContext().allocFragment(STI); - insert(IF); - IF->setInst(Inst); - + auto *F = getOrCreateDataFragment(); + SmallVector Data; SmallVector Fixups; - getAssembler().getEmitter().encodeInstruction( - Inst, IF->getContentsForAppending(), Fixups, STI); - IF->doneAppending(); - IF->appendFixups(Fixups); + getAssembler().getEmitter().encodeInstruction(Inst, Data, Fixups, STI); + + F->Kind = MCFragment::FT_Relaxable; + F->STI = &STI; + F->HasInstructions = true; + F->setVarContents(Data); + F->setVarFixups(Fixups); + F->setInst(Inst); } void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, @@ -469,9 +478,10 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, return; } - const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, SMLoc()); - insert(getContext().allocFragment(LineDelta, - *AddrDelta)); + auto *F = getOrCreateDataFragment(); + F->Kind = MCFragment::FT_Dwarf; + F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, SMLoc())); + F->setDwarfLineDelta(LineDelta); } void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section, @@ -499,8 +509,9 @@ void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section, void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label, SMLoc Loc) { - const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, Loc); - insert(getContext().allocFragment(*AddrDelta)); + auto *F = getOrCreateDataFragment(); + F->Kind = MCFragment::FT_DwarfFrame; + F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, Loc)); } void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo, @@ -559,7 +570,7 @@ void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) { void MCObjectStreamer::emitBytes(StringRef Data) { MCDwarfLineEntry::make(this, getCurrentSectionOnly()); - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); DF->appendContents(ArrayRef(Data.data(), Data.size())); } @@ -598,7 +609,7 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, static std::optional> getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset, - MCDataFragment *&DF) { + MCFragment *&DF) { if (Symbol.isVariable()) { const MCExpr *SymbolExpr = Symbol.getVariableValue(); MCValue OffsetVal; @@ -615,7 +626,7 @@ getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset, return std::make_pair(false, std::string("symbol in offset has no data " "fragment")); - DF = cast(Fragment); + DF = cast(Fragment); return std::nullopt; } @@ -643,7 +654,7 @@ getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset, std::string("symbol in offset has no data " "fragment")); RelocOffset = SA.getOffset() + OffsetVal.getConstant(); - DF = cast(Fragment); + DF = cast(Fragment); } else { RelocOffset = Symbol.getOffset(); MCFragment *Fragment = Symbol.getFragment(); @@ -653,7 +664,7 @@ getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset, return std::make_pair(false, std::string("symbol in offset has no data " "fragment")); - DF = cast(Fragment); + DF = cast(Fragment); } return std::nullopt; } @@ -674,7 +685,7 @@ MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, Expr = MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext()); - MCDataFragment *DF = getOrCreateDataFragment(&STI); + MCFragment *DF = getOrCreateDataFragment(&STI); MCValue OffsetVal; if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr)) return std::make_pair(false, diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index f1c81e90a0fe5..93671450c0c2f 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -60,7 +60,7 @@ LLVM_DUMP_METHOD void MCSection::dump( } #endif -void MCEncodedFragment::setContents(ArrayRef Contents) { +void MCFragment::setContents(ArrayRef Contents) { auto &S = getParent()->ContentStorage; if (ContentStart + Contents.size() > ContentEnd) { ContentStart = S.size(); @@ -70,9 +70,19 @@ void MCEncodedFragment::setContents(ArrayRef Contents) { llvm::copy(Contents, S.begin() + ContentStart); } -void MCEncodedFragment::addFixup(MCFixup Fixup) { appendFixups({Fixup}); } +void MCFragment::setVarContents(ArrayRef Contents) { + auto &S = getParent()->ContentStorage; + if (VarContentStart + Contents.size() > VarContentEnd) { + VarContentStart = S.size(); + S.resize_for_overwrite(S.size() + Contents.size()); + } + VarContentEnd = VarContentStart + Contents.size(); + llvm::copy(Contents, S.begin() + VarContentStart); +} + +void MCFragment::addFixup(MCFixup Fixup) { appendFixups({Fixup}); } -void MCEncodedFragment::appendFixups(ArrayRef Fixups) { +void MCFragment::appendFixups(ArrayRef Fixups) { auto &S = getParent()->FixupStorage; if (LLVM_UNLIKELY(FixupEnd != S.size())) { // Move the elements to the end. Reserve space to avoid invalidating @@ -86,7 +96,7 @@ void MCEncodedFragment::appendFixups(ArrayRef Fixups) { FixupEnd = S.size(); } -void MCEncodedFragment::setFixups(ArrayRef Fixups) { +void MCFragment::setFixups(ArrayRef Fixups) { auto &S = getParent()->FixupStorage; if (FixupStart + Fixups.size() > FixupEnd) { FixupStart = S.size(); @@ -95,3 +105,19 @@ void MCEncodedFragment::setFixups(ArrayRef Fixups) { FixupEnd = FixupStart + Fixups.size(); llvm::copy(Fixups, S.begin() + FixupStart); } + +void MCFragment::setVarFixups(ArrayRef Fixups) { + auto &S = getParent()->FixupStorage; + if (VarFixupStart + Fixups.size() > VarFixupEnd) { + VarFixupStart = S.size(); + S.resize_for_overwrite(S.size() + Fixups.size()); + } + VarFixupEnd = VarFixupStart + Fixups.size(); + // Source fixup offsets are relative to the variable part's start. Add the + // fixed part size to make them relative to the fixed part's start. + std::transform(Fixups.begin(), Fixups.end(), S.begin() + VarFixupStart, + [Fixed = getFixedSize()](MCFixup F) { + F.setOffset(Fixed + F.getOffset()); + return F; + }); +} diff --git a/llvm/lib/MC/MCSymbol.cpp b/llvm/lib/MC/MCSymbol.cpp index baf1ff89c0188..8192896eeb6bb 100644 --- a/llvm/lib/MC/MCSymbol.cpp +++ b/llvm/lib/MC/MCSymbol.cpp @@ -21,7 +21,7 @@ using namespace llvm; // Only the address of this fragment is ever actually used. -static MCDataFragment SentinelFragment; +static MCFragment SentinelFragment; // Sentinel value for the absolute pseudo fragment. MCFragment *MCSymbol::AbsolutePseudoFragment = &SentinelFragment; diff --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp index 44d98acdb31f1..5891420c0727d 100644 --- a/llvm/lib/MC/MCWasmStreamer.cpp +++ b/llvm/lib/MC/MCWasmStreamer.cpp @@ -45,7 +45,7 @@ void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { Symbol->setTLS(); } -void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F, +void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment &F, uint64_t Offset) { auto *Symbol = cast(S); MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset); diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp index 8cc74db9beea4..e8b26bf291ee4 100644 --- a/llvm/lib/MC/MCWin64EH.cpp +++ b/llvm/lib/MC/MCWin64EH.cpp @@ -318,7 +318,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { // Emit the epilog instructions. if (EnableUnwindV2) { - MCDataFragment *DF = OS->getOrCreateDataFragment(); + MCFragment *DF = OS->getOrCreateDataFragment(); bool IsLast = true; for (const auto &Epilog : llvm::reverse(info->EpilogMap)) { diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp index 0c0866f9e36a4..3398775df3f91 100644 --- a/llvm/lib/MC/MCWinCOFFStreamer.cpp +++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp @@ -278,7 +278,7 @@ void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) { void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) { visitUsedSymbol(*Symbol); - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2); DF->addFixup(Fixup); @@ -288,7 +288,7 @@ void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) { void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol, uint64_t Offset) { visitUsedSymbol(*Symbol); - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); // Create Symbol A for the relocation relative reference. const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); // Add the constant offset, if given. @@ -306,7 +306,7 @@ void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol, void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol, int64_t Offset) { visitUsedSymbol(*Symbol); - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); // Create Symbol A for the relocation relative reference. const MCExpr *MCE = MCSymbolRefExpr::create( Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext()); @@ -324,7 +324,7 @@ void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol, void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) { visitUsedSymbol(*Symbol); - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); // Create Symbol for section number. const MCExpr *MCE = MCCOFFSectionNumberTargetExpr::create( *Symbol, this->getWriter(), getContext()); @@ -338,7 +338,7 @@ void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) { void MCWinCOFFStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) { visitUsedSymbol(*Symbol); - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); // Create Symbol for section offset. const MCExpr *MCE = MCCOFFSectionOffsetTargetExpr::create(*Symbol, getContext()); diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp index 12e6680bcf074..4d4529653aba9 100644 --- a/llvm/lib/MC/MCXCOFFStreamer.cpp +++ b/llvm/lib/MC/MCXCOFFStreamer.cpp @@ -89,7 +89,7 @@ void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility( void MCXCOFFStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) { // Add a Fixup here to later record a relocation of type R_REF to prevent the // ref symbol from being garbage collected (by the binder). - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); std::optional MaybeKind = getAssembler().getBackend().getFixupKind("R_REF"); diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp index a2e73b9807bcf..9250375962732 100644 --- a/llvm/lib/MC/MachObjectWriter.cpp +++ b/llvm/lib/MC/MachObjectWriter.cpp @@ -806,7 +806,7 @@ void MachObjectWriter::prepareObject(MCAssembler &Asm) { if (!CGProfile.empty()) { MCSection *CGProfileSection = getContext().getMachOSection( "__LLVM", "__cg_profile", 0, SectionKind::getMetadata()); - auto &Frag = cast(*CGProfileSection->begin()); + auto &Frag = *CGProfileSection->begin(); Frag.clearContents(); raw_svector_ostream OS(Frag.getContentsForAppending()); for (const MCObjectWriter::CGProfileEntry &CGPE : CGProfile) { diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 4c226d4420e1d..7af240a73f952 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -711,10 +711,12 @@ static void addData(SmallVectorImpl &DataBytes, llvm_unreachable("The fill should be an assembler constant"); DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues, Fill->getValue()); - } else if (auto *LEB = dyn_cast(&Frag)) { - llvm::append_range(DataBytes, LEB->getContents()); } else { - llvm::append_range(DataBytes, cast(Frag).getContents()); + llvm::append_range(DataBytes, Frag.getContents()); + if (Frag.getKind() == MCFragment::FT_LEB) + llvm::append_range(DataBytes, Frag.getVarContents()); + else + assert(Frag.getKind() == MCFragment::FT_Data); } } @@ -1884,7 +1886,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority)) report_fatal_error("invalid .init_array section priority"); } - const auto &DataFrag = cast(Frag); + const auto &DataFrag = Frag; assert(llvm::all_of(DataFrag.getContents(), [](char C) { return !C; })); for (const MCFixup &Fixup : DataFrag.getFixups()) { assert(Fixup.getKind() == diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index c2ef430984ed4..ee4d957fe9d87 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -1069,7 +1069,7 @@ uint64_t WinCOFFWriter::writeObject() { if (Mode != DwoOnly && OWriter.getEmitAddrsigSection()) { auto *Sec = getContext().getCOFFSection(".llvm_addrsig", COFF::IMAGE_SCN_LNK_REMOVE); - auto *Frag = cast(Sec->curFragList()->Head); + auto *Frag = Sec->curFragList()->Head; raw_svector_ostream OS(Frag->getContentsForAppending()); for (const MCSymbol *S : OWriter.AddrsigSyms) { if (!S->isRegistered()) @@ -1092,7 +1092,7 @@ uint64_t WinCOFFWriter::writeObject() { if (Mode != DwoOnly && !OWriter.getCGProfile().empty()) { auto *Sec = getContext().getCOFFSection(".llvm.call-graph-profile", COFF::IMAGE_SCN_LNK_REMOVE); - auto *Frag = cast(Sec->curFragList()->Head); + auto *Frag = Sec->curFragList()->Head; raw_svector_ostream OS(Frag->getContentsForAppending()); for (const auto &CGPE : OWriter.getCGProfile()) { uint32_t FromIndex = CGPE.From->getSymbol().getIndex(); diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp index f2144375fd95e..233f42b7a4790 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -529,11 +529,9 @@ void AArch64TargetELFStreamer::finish() { static_cast(Ctx.getObjectFileInfo()->getTextSection()); bool Empty = true; for (auto &F : *Text) { - if (auto *DF = dyn_cast(&F)) { - if (!DF->getContents().empty()) { - Empty = false; - break; - } + if (F.getSize()) { + Empty = false; + break; } } if (Empty) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 164acdec4544b..146fc6704c6da 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -311,7 +311,8 @@ static bool needsInterworking(const MCAssembler &Asm, const MCSymbol *Sym, return false; } -bool ARMAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool ARMAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &Target, uint64_t Value, bool Resolved) const { diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h index 877e3afdb1d57..07d2cf784c442 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h @@ -51,7 +51,8 @@ class ARMAsmBackend : public MCAsmBackend { const char *reasonForFixupRelaxation(const MCFixup &Fixup, uint64_t Value) const; - bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, uint64_t, + bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, bool) const override; void relaxInstruction(MCInst &Inst, diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index c61e405bd3a02..910806e99836a 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -650,11 +650,11 @@ class ARMELFStreamer : public MCELFStreamer { // This is a tentative symbol, it won't really be emitted until it's // actually needed. ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); - auto *DF = dyn_cast_or_null(getCurrentFragment()); - if (!DF) + auto *DF = getCurrentFragment(); + if (DF->getKind() != MCFragment::FT_Data) return; EMS->F = DF; - EMS->Offset = DF->getContents().size(); + EMS->Offset = DF->getFixedSize(); LastEMSInfo->State = EMS_Data; return; } @@ -1145,9 +1145,8 @@ void ARMTargetELFStreamer::finish() { auto *Text = static_cast(Ctx.getObjectFileInfo()->getTextSection()); for (auto &F : *Text) - if (auto *DF = dyn_cast(&F)) - if (!DF->getContents().empty()) - return; + if (F.getSize()) + return; Text->setFlags(Text->getFlags() | ELF::SHF_ARM_PURECODE); } } diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp index 062b4356420ab..694d9eab9694b 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp @@ -157,7 +157,8 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, } } -bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &, uint64_t Value, bool Resolved) const { diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h index 1d3a22c2bbbb4..1c8516fbf53a7 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h @@ -38,7 +38,8 @@ class CSKYAsmBackend : public MCAsmBackend { void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, uint64_t, + bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, bool) const override; bool writeNopData(raw_ostream &OS, uint64_t Count, diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp index 287bdc5bfd4d4..7d3074ba6b5d2 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -46,16 +46,15 @@ class HexagonAsmBackend : public MCAsmBackend { MCInst * Extender; unsigned MaxPacketSize; - void ReplaceInstruction(MCCodeEmitter &E, MCRelaxableFragment &RF, - MCInst &HMB) const { + void ReplaceInstruction(MCCodeEmitter &E, MCFragment &RF, MCInst &HMB) const { SmallVector Fixups; SmallString<256> Code; E.encodeInstruction(HMB, Code, Fixups, *RF.getSubtargetInfo()); // Update the fragment. RF.setInst(HMB); - RF.setContents(Code); - RF.getFixups() = Fixups; + RF.setVarContents(Code); + RF.setVarFixups(Fixups); } public: @@ -438,15 +437,15 @@ class HexagonAsmBackend : public MCAsmBackend { /// fixupNeedsRelaxation - Target specific predicate for whether a given /// fixup requires the associated instruction to be relaxed. - bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, const MCValue &, - uint64_t Value, + bool fixupNeedsRelaxationAdvanced(const MCFragment &F, const MCFixup &Fixup, + const MCValue &, uint64_t Value, bool Resolved) const override { MCInst const &MCB = RelaxedMCB; assert(HexagonMCInstrInfo::isBundle(MCB)); *RelaxTarget = nullptr; MCInst &MCI = const_cast(HexagonMCInstrInfo::instruction( - MCB, Fixup.getOffset() / HEXAGON_INSTR_SIZE)); + MCB, (Fixup.getOffset() - F.getFixedSize()) / HEXAGON_INSTR_SIZE)); bool Relaxable = isInstRelaxable(MCI); if (Relaxable == false) return false; @@ -595,7 +594,7 @@ class HexagonAsmBackend : public MCAsmBackend { } case MCFragment::FT_Relaxable: { MCContext &Context = getContext(); - auto &RF = cast(*Frags[K]); + auto &RF = *Frags[K]; MCInst Inst = RF.getInst(); const bool WouldTraverseLabel = llvm::any_of( diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp index 3dbf7683cdade..7b9f1156f9102 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -279,23 +279,23 @@ getRelocPairForSize(unsigned Size) { } } -std::pair LoongArchAsmBackend::relaxLEB128(MCLEBFragment &LF, +std::pair LoongArchAsmBackend::relaxLEB128(MCFragment &F, int64_t &Value) const { - const MCExpr &Expr = LF.getValue(); - if (LF.isSigned() || !Expr.evaluateKnownAbsolute(Value, *Asm)) + const MCExpr &Expr = F.getLEBValue(); + if (F.isLEBSigned() || !Expr.evaluateKnownAbsolute(Value, *Asm)) return std::make_pair(false, false); - LF.addFixup(MCFixup::create(0, &Expr, FK_Data_leb128)); + F.setVarFixups({MCFixup::create(0, &Expr, FK_Data_leb128)}); return std::make_pair(true, true); } -bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, +bool LoongArchAsmBackend::relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const { MCContext &C = getContext(); - int64_t LineDelta = DF.getLineDelta(); - const MCExpr &AddrDelta = DF.getAddrDelta(); + int64_t LineDelta = F.getDwarfLineDelta(); + const MCExpr &AddrDelta = F.getDwarfAddrDelta(); SmallVector Fixups; - size_t OldSize = DF.getContents().size(); + size_t OldSize = F.getVarSize(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -349,17 +349,16 @@ bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, OS << uint8_t(dwarf::DW_LNS_copy); } - DF.setContents(Data); - DF.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; } -bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const { - const MCExpr &AddrDelta = DF.getAddrDelta(); +bool LoongArchAsmBackend::relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const { + const MCExpr &AddrDelta = F.getDwarfAddrDelta(); SmallVector Fixups; - size_t OldSize = DF.getContents().size(); + size_t OldSize = F.getVarContents().size(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -371,9 +370,9 @@ bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, assert(getContext().getAsmInfo()->getMinInstAlignment() == 1 && "expected 1-byte alignment"); if (Value == 0) { - DF.clearContents(); - DF.clearFixups(); - WasRelaxed = OldSize != DF.getContents().size(); + F.clearVarContents(); + F.clearVarFixups(); + WasRelaxed = OldSize != 0; return true; } @@ -405,8 +404,8 @@ bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, } else { llvm_unreachable("unsupported CFA encoding"); } - DF.setContents(Data); - DF.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h index 4446cadf11e22..b32ba067810ce 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h @@ -59,11 +59,9 @@ class LoongArchAsmBackend : public MCAsmBackend { MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override; - bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, - bool &WasRelaxed) const override; - bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const override; - std::pair relaxLEB128(MCLEBFragment &LF, + bool relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const override; + bool relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const override; + std::pair relaxLEB128(MCFragment &F, int64_t &Value) const override; bool writeNopData(raw_ostream &OS, uint64_t Count, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index e42d6c539a349..f76f8b3060d2a 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -104,7 +104,8 @@ MCFixupKindInfo RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { return Infos[Kind - FirstTargetFixupKind]; } -bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &, uint64_t Value, bool Resolved) const { @@ -301,14 +302,14 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst, Inst = std::move(Res); } -bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, +bool RISCVAsmBackend::relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const { MCContext &C = getContext(); - int64_t LineDelta = DF.getLineDelta(); - const MCExpr &AddrDelta = DF.getAddrDelta(); + int64_t LineDelta = F.getDwarfLineDelta(); + const MCExpr &AddrDelta = F.getDwarfAddrDelta(); SmallVector Fixups; - size_t OldSize = DF.getContents().size(); + size_t OldSize = F.getVarSize(); int64_t Value; [[maybe_unused]] bool IsAbsolute = @@ -361,17 +362,16 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, OS << uint8_t(dwarf::DW_LNS_copy); } - DF.setContents(Data); - DF.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; } -bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const { - const MCExpr &AddrDelta = DF.getAddrDelta(); +bool RISCVAsmBackend::relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const { + const MCExpr &AddrDelta = F.getDwarfAddrDelta(); SmallVector Fixups; - size_t OldSize = DF.getContents().size(); + size_t OldSize = F.getVarSize(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -383,9 +383,9 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, assert(getContext().getAsmInfo()->getMinInstAlignment() == 1 && "expected 1-byte alignment"); if (Value == 0) { - DF.clearContents(); - DF.clearFixups(); - WasRelaxed = OldSize != DF.getContents().size(); + F.clearVarContents(); + F.clearVarFixups(); + WasRelaxed = OldSize != 0; return true; } @@ -416,20 +416,20 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, } else { llvm_unreachable("unsupported CFA encoding"); } - DF.setContents(Data); - DF.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; } -std::pair RISCVAsmBackend::relaxLEB128(MCLEBFragment &LF, +std::pair RISCVAsmBackend::relaxLEB128(MCFragment &LF, int64_t &Value) const { - if (LF.isSigned()) + if (LF.isLEBSigned()) return std::make_pair(false, false); - const MCExpr &Expr = LF.getValue(); + const MCExpr &Expr = LF.getLEBValue(); if (ULEB128Reloc) { - LF.addFixup(MCFixup::create(0, &Expr, FK_Data_leb128)); + LF.setVarFixups({MCFixup::create(0, &Expr, FK_Data_leb128)}); } return std::make_pair(Expr.evaluateKnownAbsolute(Value, *Asm), false); } @@ -662,14 +662,13 @@ static const MCFixup *getPCRelHiFixup(const MCSpecifierExpr &Expr, const MCSymbol *AUIPCSymbol = AUIPCLoc.getAddSym(); if (!AUIPCSymbol) return nullptr; - const auto *DF = dyn_cast_or_null(AUIPCSymbol->getFragment()); - + const auto *DF = AUIPCSymbol->getFragment(); if (!DF) return nullptr; uint64_t Offset = AUIPCSymbol->getOffset(); if (DF->getContents().size() == Offset) { - DF = dyn_cast_or_null(DF->getNext()); + DF = DF->getNext(); if (!DF) return nullptr; Offset = 0; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index 1f1a6f5fe31a0..8c10fbec3c8fc 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -60,7 +60,8 @@ class RISCVAsmBackend : public MCAsmBackend { std::unique_ptr createObjectTargetWriter() const override; - bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, uint64_t, + bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, bool) const override; std::optional getFixupKind(StringRef Name) const override; @@ -72,11 +73,9 @@ class RISCVAsmBackend : public MCAsmBackend { void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, - bool &WasRelaxed) const override; - bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const override; - std::pair relaxLEB128(MCLEBFragment &LF, + bool relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const override; + bool relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const override; + std::pair relaxLEB128(MCFragment &LF, int64_t &Value) const override; bool writeNopData(raw_ostream &OS, uint64_t Count, diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index a94b2df617911..8ab76487ebec3 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -26,6 +26,7 @@ #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/TargetRegistry.h" @@ -177,20 +178,20 @@ class X86AsmBackend : public MCAsmBackend { bool mayNeedRelaxation(unsigned Opcode, ArrayRef Operands, const MCSubtargetInfo &STI) const override; - bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, uint64_t, + bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, bool) const override; void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool padInstructionViaRelaxation(MCRelaxableFragment &RF, - MCCodeEmitter &Emitter, + bool padInstructionViaRelaxation(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const; - bool padInstructionViaPrefix(MCRelaxableFragment &RF, MCCodeEmitter &Emitter, + bool padInstructionViaPrefix(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const; - bool padInstructionEncoding(MCRelaxableFragment &RF, MCCodeEmitter &Emitter, + bool padInstructionEncoding(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const; bool finishLayout(const MCAssembler &Asm) const override; @@ -409,10 +410,9 @@ isRightAfterData(MCFragment *CurrentFragment, // it, returns true. // - Otherwise returns false. // - If the fragment is not a DataFragment, returns false. - if (auto *DF = dyn_cast_or_null(F)) - return DF->getContents().size() && - (DF != PrevInstPosition.first || - DF->getContents().size() != PrevInstPosition.second); + if (F->getKind() == MCFragment::FT_Data) + return F->getFixedSize() && (F != PrevInstPosition.first || + F->getFixedSize() != PrevInstPosition.second); return false; } @@ -421,11 +421,7 @@ isRightAfterData(MCFragment *CurrentFragment, static size_t getSizeForInstFragment(const MCFragment *F) { if (!F || !F->hasInstructions()) return 0; - // MCEncodedFragmentWithContents being templated makes this tricky. - if (auto *DF = dyn_cast(F)) - return DF->getContents().size(); - else - llvm_unreachable("Unknown fragment with instructions!"); + return F->getSize(); } /// Return true if we can insert NOP or prefixes automatically before the @@ -547,8 +543,8 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS, void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) { MCFragment *CF = OS.getCurrentFragment(); - if (auto *F = dyn_cast_or_null(CF)) - F->setAllowAutoPadding(canPadInst(Inst, OS)); + if (CF->getKind() == MCFragment::FT_Relaxable) + CF->setAllowAutoPadding(canPadInst(Inst, OS)); // Update PrevInstOpcode here, canPadInst() reads that. PrevInstOpcode = Inst.getOpcode(); @@ -752,7 +748,8 @@ bool X86AsmBackend::mayNeedRelaxation(unsigned Opcode, Operands[Operands.size() - 1 - SkipOperands].isExpr()); } -bool X86AsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool X86AsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &Target, uint64_t Value, bool Resolved) const { @@ -781,7 +778,7 @@ void X86AsmBackend::relaxInstruction(MCInst &Inst, Inst.setOpcode(RelaxedOp); } -bool X86AsmBackend::padInstructionViaPrefix(MCRelaxableFragment &RF, +bool X86AsmBackend::padInstructionViaPrefix(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const { if (!RF.getAllowAutoPadding()) @@ -794,7 +791,7 @@ bool X86AsmBackend::padInstructionViaPrefix(MCRelaxableFragment &RF, *RF.getSubtargetInfo())) return false; - const unsigned OldSize = RF.getContents().size(); + const unsigned OldSize = RF.getVarSize(); if (OldSize == 15) return false; @@ -823,19 +820,18 @@ bool X86AsmBackend::padInstructionViaPrefix(MCRelaxableFragment &RF, SmallString<256> Code; Code.append(PrefixBytesToAdd, Prefix); - Code.append(RF.getContents().begin(), RF.getContents().end()); - RF.setContents(Code); + Code.append(RF.getVarContents().begin(), RF.getVarContents().end()); + RF.setVarContents(Code); // Adjust the fixups for the change in offsets - for (auto &F : RF.getFixups()) { - F.setOffset(F.getOffset() + PrefixBytesToAdd); - } + for (auto &F : RF.getVarFixups()) + F.setOffset(PrefixBytesToAdd + F.getOffset()); RemainingSize -= PrefixBytesToAdd; return true; } -bool X86AsmBackend::padInstructionViaRelaxation(MCRelaxableFragment &RF, +bool X86AsmBackend::padInstructionViaRelaxation(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const { if (!mayNeedRelaxation(RF.getOpcode(), RF.getOperands(), @@ -850,20 +846,20 @@ bool X86AsmBackend::padInstructionViaRelaxation(MCRelaxableFragment &RF, SmallVector Fixups; SmallString<15> Code; Emitter.encodeInstruction(Relaxed, Code, Fixups, *RF.getSubtargetInfo()); - const unsigned OldSize = RF.getContents().size(); + const unsigned OldSize = RF.getVarContents().size(); const unsigned NewSize = Code.size(); assert(NewSize >= OldSize && "size decrease during relaxation?"); unsigned Delta = NewSize - OldSize; if (Delta > RemainingSize) return false; RF.setInst(Relaxed); - RF.setContents(Code); - RF.setFixups(Fixups); + RF.setVarContents(Code); + RF.setVarFixups(Fixups); RemainingSize -= Delta; return true; } -bool X86AsmBackend::padInstructionEncoding(MCRelaxableFragment &RF, +bool X86AsmBackend::padInstructionEncoding(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const { bool Changed = false; @@ -896,7 +892,7 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const { if (!Sec.isText()) continue; - SmallVector Relaxable; + SmallVector Relaxable; for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) { MCFragment &F = *I; @@ -907,7 +903,7 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const { continue; if (F.getKind() == MCFragment::FT_Relaxable) { - auto &RF = cast(*I); + auto &RF = cast(*I); Relaxable.push_back(&RF); continue; } diff --git a/llvm/test/MC/ELF/mc-dump.s b/llvm/test/MC/ELF/mc-dump.s index 9cf15a7ddee46..5cc2e9fa50179 100644 --- a/llvm/test/MC/ELF/mc-dump.s +++ b/llvm/test/MC/ELF/mc-dump.s @@ -11,40 +11,46 @@ # CHECK-NEXT:0 Align Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 Nops # CHECK-NEXT:0 Data Size:0 [] # CHECK-NEXT: Symbol @0 _start +# CHECK-NEXT: Symbol @0 Temporary # CHECK-NEXT:0 Org Offset:3 Value:0 -# CHECK-NEXT:3 Relaxable Size:2 > +# CHECK-NEXT:3 Relaxable Size:0+2 [eb,00] > # CHECK-NEXT: Fixup @1 Value:.Ltmp0 Kind:4001 # CHECK-NEXT:5 Data Size:16 [48,8b,04,25,00,00,00,00,48,8b,04,25,00,00,00,00] # CHECK-NEXT: Fixup @4 Value:f0@ Kind:4017 # CHECK-NEXT: Fixup @12 Value:_start@ Kind:4017 # CHECK-NEXT: Symbol @16 .Ltmp0 Temporary +# CHECK-NEXT: Symbol @0 Temporary +# CHECK-NEXT: Symbol @16 Temporary # CHECK-NEXT:MCSection Name:.data # CHECK-NEXT:0 Data Size:0 [] # CHECK-NEXT: Symbol @0 .data # CHECK-NEXT:0 Align Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 # CHECK-NEXT:0 Data Size:4 [01,00,00,00] # CHECK-NEXT:4 Fill Value:0 ValueSize:1 NumValues:1 -# CHECK-NEXT:5 LEB Value:.Ltmp0-_start Signed:0 -# CHECK-NEXT:] +# CHECK-NEXT:5 LEB Size:0+1 [15] Value:.Ltmp0-_start Signed:0 +# CHECK:] # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t -debug-only=mc-dump -save-temp-labels -g 2>&1 | FileCheck %s --check-prefix=CHECK2 # CHECK2:5 Data Size:16 [48,8b,04,25,00,00,00,00,48,8b,04,25,00,00,00,00] # CHECK2-NEXT: Fixup @4 Value:f0@ Kind:4017 # CHECK2-NEXT: Fixup @12 Value:_start@ Kind:4017 -# CHECK2-NEXT: Symbol @16 .Ltmp1 -# CHECK2-NEXT: Symbol @0 .Ltmp3 Temporary -# CHECK2-NEXT: Symbol @8 .Ltmp4 Temporary -# CHECK2-NEXT: Symbol @16 .Ltmp5 Temporary -# CHECK2-NEXT: Symbol @16 .Lsec_end0 Temporary +# CHECK2-NEXT: Symbol @16 .Ltmp2 +# CHECK2-NEXT: Symbol @0 .Lcfi0 Temporary +# CHECK2:MCSection Name:.eh_frame +# CHECK2:24 DwarfCallFrame Size:17+1 [00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,45] AddrDelta:.Lcfi0-.Ltmp1 +# CHECK2-NEXT: Fixup @0 Value:.Ltmp12-.Ltmp11-0 Kind:4003 _start: var = _start +.cfi_startproc .org 3 jmp 1f +.cfi_offset %rbp, -24 movq f0@GOTPCREL, %rax movq _start@GOTPCREL, %rax 1: +.cfi_endproc .data .p2align 2 From ec83ebf8bf1e3c17cb1638cb100c2ad7ca9178ff Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 15 Jul 2025 22:14:39 -0700 Subject: [PATCH 04/39] MCFragment: Remove MCDataFragment/MCRelaxableFragment type aliases Follow-up to #148544 --- llvm/include/llvm/MC/MCAsmBackend.h | 3 +-- llvm/include/llvm/MC/MCSection.h | 14 +++++--------- llvm/lib/MC/MCAssembler.cpp | 3 +-- llvm/lib/MC/MCFragment.cpp | 2 +- .../lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp | 8 ++++---- .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 12 ++++++------ .../Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp | 9 ++++----- llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 3 +-- 8 files changed, 23 insertions(+), 31 deletions(-) diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index 09cc367837117..62a5e013259df 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -242,8 +242,7 @@ class LLVM_ABI MCAsmBackend { bool isDarwinCanonicalPersonality(const MCSymbol *Sym) const; - // Return STI for fragments of type MCRelaxableFragment and MCFragment - // with hasInstructions() == true. + // Return STI for fragments with hasInstructions() == true. static const MCSubtargetInfo *getSubtargetInfo(const MCFragment &F); }; diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 362893c5e4361..28efe0a3b57d5 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -226,13 +226,13 @@ class MCFragment { FragmentType Kind; protected: - /// Used by subclasses for better packing. + bool LinkerRelaxable : 1; + + /// Used by certain fragment types for better packing. /// - /// MCEncodedFragment + /// FT_Data, FT_Relaxable bool HasInstructions : 1; - /// MCDataFragment - bool LinkerRelaxable : 1; - /// MCRelaxableFragment: x86-specific + /// FT_Relaxable, x86-specific bool AllowAutoPadding : 1; uint32_t ContentStart = 0; @@ -487,10 +487,6 @@ class MCEncodedFragment : public MCFragment { : MCFragment(FType, HasInstructions) {} }; -// TODO Delete -using MCDataFragment = MCFragment; -using MCRelaxableFragment = MCFragment; - class MCAlignFragment : public MCFragment { /// Flag to indicate that (optimal) NOPs should be emitted instead /// of using the provided value. The exact interpretation of this flag is diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 77741a60d0408..d4d10e0cd74a5 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -966,8 +966,7 @@ bool MCAssembler::relaxFragment(MCFragment &F) { default: return false; case MCFragment::FT_Relaxable: - assert(!getRelaxAll() && - "Did not expect a MCRelaxableFragment in RelaxAll mode"); + assert(!getRelaxAll() && "Did not expect a FT_Relaxable in RelaxAll mode"); return relaxInstruction(F); case MCFragment::FT_LEB: return relaxLEB(F); diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index 49760a69a44cc..bfe045abe6e53 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -28,7 +28,7 @@ static_assert(std::is_trivially_destructible_v, "fragment classes must be trivially destructible"); MCFragment::MCFragment(FragmentType Kind, bool HasInstructions) - : Kind(Kind), HasInstructions(HasInstructions), LinkerRelaxable(false), + : Kind(Kind), LinkerRelaxable(false), HasInstructions(HasInstructions), AllowAutoPadding(false) { static_assert(sizeof(MCFragment::Tail) <= 16, "Keep the variable-size tail small"); diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index 910806e99836a..eaba6fe5bfcb7 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -638,7 +638,7 @@ class ARMELFStreamer : public MCELFStreamer { Offset = 0; } bool hasInfo() { return F != nullptr; } - MCDataFragment *F = nullptr; + MCFragment *F = nullptr; uint64_t Offset = 0; ElfMappingSymbol State = EMS_None; }; @@ -686,7 +686,7 @@ class ARMELFStreamer : public MCELFStreamer { Symbol->setBinding(ELF::STB_LOCAL); } - void emitMappingSymbol(StringRef Name, MCDataFragment &F, uint64_t Offset) { + void emitMappingSymbol(StringRef Name, MCFragment &F, uint64_t Offset) { auto *Symbol = cast(getContext().createLocalSymbol(Name)); emitLabelAtPos(Symbol, SMLoc(), F, Offset); Symbol->setType(ELF::STT_NOTYPE); @@ -1207,7 +1207,7 @@ inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) { } void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) { - MCDataFragment *Frag = getOrCreateDataFragment(); + MCFragment *Frag = getOrCreateDataFragment(); Frag->addFixup(MCFixup::create(Frag->getContents().size(), Expr, Kind)); } @@ -1295,7 +1295,7 @@ void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) { MCSymbolRefExpr::create(PersonalitySym, ARM::S_ARM_NONE, getContext()); visitUsedExpr(*PersonalityRef); - MCDataFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getOrCreateDataFragment(); DF->addFixup( MCFixup::create(DF->getContents().size(), PersonalityRef, FK_Data_4)); } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index c69fc68ab5af1..b89d6890903dd 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -1033,42 +1033,42 @@ MCELFStreamer &MipsTargetELFStreamer::getStreamer() { } void MipsTargetELFStreamer::emitGPRel32Value(const MCExpr *Value) { - MCDataFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getOrCreateDataFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_GPREL32)); DF->appendContents(4, 0); } void MipsTargetELFStreamer::emitGPRel64Value(const MCExpr *Value) { - MCDataFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getOrCreateDataFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_GPREL32)); DF->appendContents(8, 0); } void MipsTargetELFStreamer::emitDTPRel32Value(const MCExpr *Value) { - MCDataFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getOrCreateDataFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_DTPREL32)); DF->appendContents(4, 0); } void MipsTargetELFStreamer::emitDTPRel64Value(const MCExpr *Value) { - MCDataFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getOrCreateDataFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_DTPREL64)); DF->appendContents(8, 0); } void MipsTargetELFStreamer::emitTPRel32Value(const MCExpr *Value) { - MCDataFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getOrCreateDataFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_TPREL32)); DF->appendContents(4, 0); } void MipsTargetELFStreamer::emitTPRel64Value(const MCExpr *Value) { - MCDataFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getOrCreateDataFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_TPREL64)); DF->appendContents(8, 0); diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp index ee99cfc7d655d..2dbc31fce72c2 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp @@ -155,11 +155,10 @@ void PPCELFStreamer::emitGOTToPCRelReloc(const MCInst &Inst) { const MCExpr *SubExpr2 = MCBinaryExpr::createSub(CurrentLocationExpr, SubExpr, getContext()); - MCDataFragment *DF = static_cast(LabelSym->getFragment()); - assert(DF && "Expecting a valid data fragment."); - MCFixupKind FixupKind = static_cast(FirstLiteralRelocationKind + - ELF::R_PPC64_PCREL_OPT); - DF->addFixup(MCFixup::create(LabelSym->getOffset() - 8, SubExpr2, FixupKind)); + MCFragment *F = LabelSym->getFragment(); + F->addFixup( + MCFixup::create(LabelSym->getOffset() - 8, SubExpr2, + FirstLiteralRelocationKind + ELF::R_PPC64_PCREL_OPT)); emitLabel(CurrentLocation, Inst.getLoc()); } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 8ab76487ebec3..3d060c6f4a780 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -567,8 +567,7 @@ void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, // DataFragment, so that we can get the size of instructions later in // MCAssembler::relaxBoundaryAlign. The easiest way is to insert a new empty // DataFragment. - if (isa_and_nonnull(CF)) - OS.insert(OS.getContext().allocFragment()); + OS.insert(OS.getContext().allocFragment()); // Update the maximum alignment on the current section if necessary. MCSection *Sec = OS.getCurrentSectionOnly(); From 4c55edcb7e797efe67bb1219aca485a80f552734 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 17 Jul 2025 00:36:10 -0700 Subject: [PATCH 05/39] MC: Rework .reloc directive and fix the offset when it evaluates to a constant * Fix `.reloc constant` to mean section_symbol+constant instead of .+constant . The initial .reloc support from MIPS incorrectly interpreted the offset. * Delay the evaluation of the offset expression after MCAssembler::layout, deleting a lot of code working with MCFragment. * Delete many FIXME from https://reviews.llvm.org/D79625 * Some lld/ELF/Arch/LoongArch.cpp relaxation tests rely on .reloc ., R_LARCH_ALIGN generating ALIGN relocations at specific location. Sort the relocations. --- lld/ELF/Relocations.cpp | 5 +- llvm/include/llvm/MC/MCAssembler.h | 8 + llvm/include/llvm/MC/MCELFStreamer.h | 3 +- llvm/include/llvm/MC/MCObjectStreamer.h | 14 +- llvm/include/llvm/MC/MCStreamer.h | 10 +- llvm/lib/MC/MCAsmStreamer.cpp | 12 +- llvm/lib/MC/MCAssembler.cpp | 25 +++ llvm/lib/MC/MCELFStreamer.cpp | 21 ++- llvm/lib/MC/MCObjectStreamer.cpp | 142 ++---------------- llvm/lib/MC/MCParser/AsmParser.cpp | 9 +- .../MCTargetDesc/AArch64ELFStreamer.cpp | 3 +- .../Target/Mips/AsmParser/MipsAsmParser.cpp | 2 +- llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 2 +- llvm/test/MC/ELF/reloc-directive.s | 51 ++++--- llvm/test/MC/Mips/reloc-directive-bad-obj.s | 4 +- .../MC/Mips/reloc-directive-label-offset.s | 8 +- 16 files changed, 113 insertions(+), 206 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index cebd564036b2c..4333b032c9d4e 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1671,8 +1671,9 @@ void RelocationScanner::scan(Relocs rels) { } // Sort relocations by offset for more efficient searching for - // R_RISCV_PCREL_HI20, R_PPC64_ADDR64 and the branch-to-branch optimization. - if (ctx.arg.emachine == EM_RISCV || + // R_RISCV_PCREL_HI20, ALIGN relocations, R_PPC64_ADDR64 and the + // branch-to-branch optimization. + if (is_contained({EM_RISCV, EM_LOONGARCH}, ctx.arg.emachine) || (ctx.arg.emachine == EM_PPC64 && sec->name == ".toc") || ctx.arg.branchToBranch) llvm::stable_sort(sec->relocs(), diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index aa396efa9f018..ade9ee6fa56e0 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -69,6 +69,13 @@ class MCAssembler { SmallVector Symbols; + struct RelocDirective { + const MCExpr &Offset; + const MCExpr *Expr; + uint32_t Kind; + }; + SmallVector relocDirectives; + mutable SmallVector, 0> PendingErrors; MCDwarfLineTableParams LTParams; @@ -205,6 +212,7 @@ class MCAssembler { LLVM_ABI bool registerSection(MCSection &Section); LLVM_ABI bool registerSymbol(const MCSymbol &Symbol); + void addRelocDirective(RelocDirective RD); LLVM_ABI void reportError(SMLoc L, const Twine &Msg) const; // Record pending errors during layout iteration, as they may go away once the diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h index ad0961c8bcf97..144f6bc3bd91c 100644 --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -141,7 +141,8 @@ class MCELFStreamer : public MCObjectStreamer { } private: - void finalizeCGProfileEntry(const MCSymbolRefExpr *&S, uint64_t Offset); + void finalizeCGProfileEntry(const MCSymbolRefExpr *Sym, uint64_t Offset, + const MCSymbolRefExpr *&S); void finalizeCGProfile(); bool SeenIdent = false; diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index e2a77b809b6ca..a55fd4a14675f 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -40,14 +40,6 @@ class MCObjectStreamer : public MCStreamer { std::unique_ptr Assembler; bool EmitEHFrame; bool EmitDebugFrame; - struct PendingMCFixup { - const MCSymbol *Sym; - MCFixup Fixup; - MCFragment *DF; - PendingMCFixup(const MCSymbol *McSym, MCFragment *F, MCFixup McFixup) - : Sym(McSym), Fixup(McFixup), DF(F) {} - }; - SmallVector PendingFixups; struct PendingAssignment { MCSymbol *Symbol; @@ -63,7 +55,6 @@ class MCObjectStreamer : public MCStreamer { void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; void emitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI); - void resolvePendingFixups(); protected: MCObjectStreamer(MCContext &Context, std::unique_ptr TAB, @@ -162,9 +153,8 @@ class MCObjectStreamer : public MCStreamer { void emitCVStringTableDirective() override; void emitCVFileChecksumsDirective() override; void emitCVFileChecksumOffsetDirective(unsigned FileNo) override; - std::optional> - emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, - SMLoc Loc, const MCSubtargetInfo &STI) override; + void emitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc Loc = {}) override; using MCStreamer::emitFill; void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc = SMLoc()) override; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index df150701bb3c5..2cd621296ce76 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -1061,13 +1061,9 @@ class LLVM_ABI MCStreamer { virtual void emitSyntaxDirective(); - /// Record a relocation described by the .reloc directive. Return std::nullopt - /// if succeeded. Otherwise, return a pair (Name is invalid, error message). - virtual std::optional> - emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, - SMLoc Loc, const MCSubtargetInfo &STI) { - return std::nullopt; - } + /// Record a relocation described by the .reloc directive. + virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc Loc = {}) {} virtual void emitAddrsig() {} virtual void emitAddrsigSym(const MCSymbol *Sym) {} diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 9b5194b98651d..3ec236df312ea 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -409,9 +409,8 @@ class MCAsmStreamer final : public MCStreamer { const MCPseudoProbeInlineStack &InlineStack, MCSymbol *FnSym) override; - std::optional> - emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, - SMLoc Loc, const MCSubtargetInfo &STI) override; + void emitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc Loc) override; void emitAddrsig() override; void emitAddrsigSym(const MCSymbol *Sym) override; @@ -2480,10 +2479,8 @@ void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index, EmitEOL(); } -std::optional> -MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc, - const MCSubtargetInfo &STI) { +void MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc) { OS << "\t.reloc "; MAI->printExpr(OS, Offset); OS << ", " << Name; @@ -2492,7 +2489,6 @@ MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, MAI->printExpr(OS, *Expr); } EmitEOL(); - return std::nullopt; } void MCAsmStreamer::emitAddrsig() { diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index d4d10e0cd74a5..f1a82f6b08d31 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -398,6 +398,10 @@ bool MCAssembler::registerSymbol(const MCSymbol &Symbol) { return Changed; } +void MCAssembler::addRelocDirective(RelocDirective RD) { + relocDirectives.push_back(RD); +} + /// Write the fragment \p F to the output file. static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, const MCFragment &F) { @@ -695,6 +699,27 @@ void MCAssembler::layout() { // helps check whether a PC-relative fixup is fully resolved. this->HasFinalLayout = true; + // Resolve .reloc offsets and add fixups. + for (auto &PF : relocDirectives) { + MCValue Res; + auto &O = PF.Offset; + if (!O.evaluateAsValue(Res, *this)) { + getContext().reportError(O.getLoc(), ".reloc offset is not relocatable"); + continue; + } + auto *Sym = Res.getAddSym(); + auto *F = Sym ? Sym->getFragment() : nullptr; + auto *Sec = F ? F->getParent() : nullptr; + if (Res.getSubSym() || !Sec) { + getContext().reportError(O.getLoc(), + ".reloc offset is not relative to a section"); + continue; + } + + uint64_t Offset = Sym ? Sym->getOffset() + Res.getConstant() : 0; + F->addFixup(MCFixup::create(Offset, PF.Expr, PF.Kind)); + } + // Evaluate and apply the fixups, generating relocation entries as necessary. for (MCSection &Sec : *this) { for (MCFragment &F : Sec) { diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index ffc57227cff16..49071bdec3dbd 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -314,8 +314,9 @@ void MCELFStreamer::emitIdent(StringRef IdentString) { popSection(); } -void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE, - uint64_t Offset) { +void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *Sym, + uint64_t Offset, + const MCSymbolRefExpr *&SRE) { const MCSymbol *S = &SRE->getSymbol(); if (S->isTemporary()) { if (!S->isInSection()) { @@ -328,13 +329,9 @@ void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE, S->setUsedInReloc(); SRE = MCSymbolRefExpr::create(S, getContext(), SRE->getLoc()); } - const MCConstantExpr *MCOffset = MCConstantExpr::create(Offset, getContext()); - if (std::optional> Err = - MCObjectStreamer::emitRelocDirective( - *MCOffset, "BFD_RELOC_NONE", SRE, SRE->getLoc(), - *getContext().getSubtargetInfo())) - report_fatal_error("Relocation for CG Profile could not be created: " + - Twine(Err->second)); + auto *O = MCBinaryExpr::createAdd( + Sym, MCConstantExpr::create(Offset, getContext()), getContext()); + MCObjectStreamer::emitRelocDirective(*O, "BFD_RELOC_NONE", SRE); } void MCELFStreamer::finalizeCGProfile() { @@ -347,9 +344,11 @@ void MCELFStreamer::finalizeCGProfile() { pushSection(); switchSection(CGProfile); uint64_t Offset = 0; + auto *Sym = + MCSymbolRefExpr::create(CGProfile->getBeginSymbol(), getContext()); for (auto &E : W.getCGProfile()) { - finalizeCGProfileEntry(E.From, Offset); - finalizeCGProfileEntry(E.To, Offset); + finalizeCGProfileEntry(Sym, Offset, E.From); + finalizeCGProfileEntry(Sym, Offset, E.To); emitIntValue(E.Count, sizeof(uint64_t)); Offset += sizeof(uint64_t); } diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index c0cef0f06c57a..67433f2b265e5 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -46,35 +46,6 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() { return nullptr; } -// When fixup's offset is a forward declared label, e.g.: -// -// .reloc 1f, R_MIPS_JALR, foo -// 1: nop -// -// postpone adding it to Fixups vector until the label is defined and its offset -// is known. -void MCObjectStreamer::resolvePendingFixups() { - for (PendingMCFixup &PendingFixup : PendingFixups) { - if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) { - getContext().reportError(PendingFixup.Fixup.getLoc(), - "unresolved relocation offset"); - continue; - } - PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() + - PendingFixup.Fixup.getOffset()); - - // If the location symbol to relocate is in MCEncodedFragment, - // put the Fixup into location symbol's fragment. Otherwise - // put into PendingFixup.DF - MCFragment *F = PendingFixup.Sym->getFragment(); - if (F->isEncoded()) - F->addFixup(PendingFixup.Fixup); - else - PendingFixup.DF->addFixup(PendingFixup.Fixup); - } - PendingFixups.clear(); -} - // As a compile-time optimization, avoid allocating and evaluating an MCExpr // tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed // part. @@ -607,76 +578,14 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, insert(getContext().allocFragment(*Offset, Value, Loc)); } -static std::optional> -getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset, - MCFragment *&DF) { - if (Symbol.isVariable()) { - const MCExpr *SymbolExpr = Symbol.getVariableValue(); - MCValue OffsetVal; - if (!SymbolExpr->evaluateAsRelocatable(OffsetVal, nullptr)) - return std::make_pair(false, - std::string("symbol in .reloc offset is not " - "relocatable")); - if (OffsetVal.isAbsolute()) { - RelocOffset = OffsetVal.getConstant(); - MCFragment *Fragment = Symbol.getFragment(); - // FIXME Support symbols with no DF. For example: - // .reloc .data, ENUM_VALUE, - if (!Fragment || Fragment->getKind() != MCFragment::FT_Data) - return std::make_pair(false, - std::string("symbol in offset has no data " - "fragment")); - DF = cast(Fragment); - return std::nullopt; - } - - if (OffsetVal.getSubSym()) - return std::make_pair(false, - std::string(".reloc symbol offset is not " - "representable")); - - const MCSymbol &SA = *OffsetVal.getAddSym(); - if (!SA.isDefined()) - return std::make_pair(false, - std::string("symbol used in the .reloc offset is " - "not defined")); - - if (SA.isVariable()) - return std::make_pair(false, - std::string("symbol used in the .reloc offset is " - "variable")); - - MCFragment *Fragment = SA.getFragment(); - // FIXME Support symbols with no DF. For example: - // .reloc .data, ENUM_VALUE, - if (!Fragment || Fragment->getKind() != MCFragment::FT_Data) - return std::make_pair(false, - std::string("symbol in offset has no data " - "fragment")); - RelocOffset = SA.getOffset() + OffsetVal.getConstant(); - DF = cast(Fragment); - } else { - RelocOffset = Symbol.getOffset(); - MCFragment *Fragment = Symbol.getFragment(); - // FIXME Support symbols with no DF. For example: - // .reloc .data, ENUM_VALUE, - if (!Fragment || Fragment->getKind() != MCFragment::FT_Data) - return std::make_pair(false, - std::string("symbol in offset has no data " - "fragment")); - DF = cast(Fragment); - } - return std::nullopt; -} - -std::optional> -MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc, - const MCSubtargetInfo &STI) { +void MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc Loc) { std::optional MaybeKind = Assembler->getBackend().getFixupKind(Name); - if (!MaybeKind) - return std::make_pair(true, std::string("unknown relocation name")); + if (!MaybeKind) { + getContext().reportError(Loc, "unknown relocation name"); + return; + } MCFixupKind Kind = *MaybeKind; if (Expr) @@ -685,38 +594,14 @@ MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, Expr = MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext()); - MCFragment *DF = getOrCreateDataFragment(&STI); - MCValue OffsetVal; - if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr)) - return std::make_pair(false, - std::string(".reloc offset is not relocatable")); - if (OffsetVal.isAbsolute()) { - if (OffsetVal.getConstant() < 0) - return std::make_pair(false, std::string(".reloc offset is negative")); - DF->addFixup(MCFixup::create(OffsetVal.getConstant(), Expr, Kind)); - return std::nullopt; - } - if (OffsetVal.getSubSym()) - return std::make_pair(false, - std::string(".reloc offset is not representable")); - - const MCSymbol &Symbol = *OffsetVal.getAddSym(); - if (Symbol.isDefined()) { - uint32_t SymbolOffset = 0; - std::optional> Error = - getOffsetAndDataFragment(Symbol, SymbolOffset, DF); - - if (Error != std::nullopt) - return Error; - - DF->addFixup( - MCFixup::create(SymbolOffset + OffsetVal.getConstant(), Expr, Kind)); - return std::nullopt; + auto *O = &Offset; + int64_t Val; + if (Offset.evaluateAsAbsolute(Val, nullptr)) { + auto *SecSym = getCurrentSectionOnly()->getBeginSymbol(); + O = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(SecSym, getContext()), + O, getContext(), Loc); } - - PendingFixups.emplace_back( - &Symbol, DF, MCFixup::create(OffsetVal.getConstant(), Expr, Kind)); - return std::nullopt; + getAssembler().addRelocDirective({*O, Expr, Kind}); } void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, @@ -799,6 +684,5 @@ void MCObjectStreamer::finishImpl() { // Emit pseudo probes for the current module. MCPseudoProbeTable::emit(this); - resolvePendingFixups(); getAssembler().Finish(); } diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index a36b2dea70ccf..77bf84364c5a3 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -3079,7 +3079,6 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { const MCExpr *Offset; const MCExpr *Expr = nullptr; - SMLoc OffsetLoc = Lexer.getTok().getLoc(); if (parseExpression(Offset)) return true; @@ -3105,13 +3104,7 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { if (parseEOL()) return true; - const MCTargetAsmParser &MCT = getTargetParser(); - const MCSubtargetInfo &STI = MCT.getSTI(); - if (std::optional> Err = - getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc, - STI)) - return Error(Err->first ? NameLoc : OffsetLoc, Err->second); - + getStreamer().emitRelocDirective(*Offset, Name, Expr, NameLoc); return false; } diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp index 233f42b7a4790..08f547a85073e 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -559,8 +559,7 @@ void AArch64TargetELFStreamer::finish() { if (!Sym.isMemtag()) continue; auto *SRE = MCSymbolRefExpr::create(&Sym, Ctx); - (void)S.emitRelocDirective(*Zero, "BFD_RELOC_NONE", SRE, SMLoc(), - *Ctx.getSubtargetInfo()); + S.emitRelocDirective(*Zero, "BFD_RELOC_NONE", SRE); } } diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 01e4d17f6236d..259b71b37d9a3 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -2101,7 +2101,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, TOut.getStreamer().emitRelocDirective( *TmpExpr, inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR", - RelocJalrExpr, IDLoc, *STI); + RelocJalrExpr); TOut.getStreamer().emitLabel(TmpLabel); } diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index c18ba44bea08e..ca0331006be74 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -166,7 +166,7 @@ static void emitDirectiveRelocJalr(const MachineInstr &MI, OutStreamer.emitRelocDirective( *OffsetExpr, Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR", - CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo()); + CaleeExpr); OutStreamer.emitLabel(OffsetLabel); return; } diff --git a/llvm/test/MC/ELF/reloc-directive.s b/llvm/test/MC/ELF/reloc-directive.s index 42995aa9e7d81..9871fba2e0021 100644 --- a/llvm/test/MC/ELF/reloc-directive.s +++ b/llvm/test/MC/ELF/reloc-directive.s @@ -9,15 +9,18 @@ # ASM-NEXT: .reloc .Ltmp1-1, R_X86_64_NONE, foo # ASM-NEXT: .Ltmp2: # ASM-NEXT: .reloc 2+.Ltmp2, R_X86_64_NONE, local -# ASM-NEXT: .reloc 1+foo+3, R_X86_64_NONE, data+1 -# ASM-NEXT: .Ltmp3: -# ASM-NEXT: .reloc .Ltmp3, BFD_RELOC_NONE, unused # CHECK: 0x2 R_X86_64_NONE foo 0x0 # CHECK-NEXT: 0x0 R_X86_64_NONE foo 0x0 # CHECK-NEXT: 0x3 R_X86_64_NONE local 0x0 -# CHECK-NEXT: 0x4 R_X86_64_NONE data 0x1 # CHECK-NEXT: 0x1 R_X86_64_NONE unused 0x0 +# CHECK-NEXT: 0x4 R_X86_64_NONE data 0x1 + +# CHECK: .rela.my { +# CHECK: 0x0 R_X86_64_NONE foo 0x0 +# CHECK-NEXT: 0x4 R_X86_64_NONE foo 0x0 +# CHECK-NEXT: 0x8 R_X86_64_NONE foo 0x0 +# CHECK-NEXT: } .text .globl foo @@ -27,17 +30,25 @@ local: .reloc .+3-2, R_X86_64_NONE, foo .reloc .-1, R_X86_64_NONE, foo .reloc 2+., R_X86_64_NONE, local - .reloc 1+foo+3, R_X86_64_NONE, data+1 .reloc ., BFD_RELOC_NONE, unused + .space 3 .data .globl data data: + .reloc 1+foo+3, R_X86_64_NONE, data+1 .long 0 -# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym=ERR=1 %s 2>&1 | FileCheck %s --check-prefix=ERR +## Constant offsets are relative to the section start. +.section .my +.word 0 +.reloc 0, BFD_RELOC_NONE, foo +.word 0 +.p2align 3 +.reloc 2+2, BFD_RELOC_NONE, foo +.p2align 4 +.reloc 8, BFD_RELOC_NONE, foo -.ifdef ERR .text .globl a, b a: ret @@ -45,22 +56,26 @@ b: ret x: ret y: ret -# ERR: {{.*}}.s:[[#@LINE+1]]:10: error: expected comma +# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym=PARSE=1 %s 2>&1 | FileCheck %s --check-prefix=PARSE +# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym=ERR=1 %s 2>&1 | FileCheck %s --check-prefix=ERR + +.ifdef PARSE +# PARSE: {{.*}}.s:[[#@LINE+1]]:10: error: expected comma .reloc 0 R_X86_64_NONE, a -# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is negative +# PARSE: {{.*}}.s:[[#@LINE+1]]:8: error: directional label undefined +.reloc 1f, R_X86_64_NONE, a +.endif + +.ifdef ERR .reloc -1, R_X86_64_NONE, a -# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not relocatable +# ERR: {{.*}}.s:[[#@LINE+1]]:9: error: .reloc offset is not relocatable .reloc 2*., R_X86_64_NONE, a -# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not relocatable +# ERR: {{.*}}.s:[[#@LINE+1]]:9: error: .reloc offset is not relocatable .reloc a+a, R_X86_64_NONE, a -## GNU as accepts a-a but rejects b-a. -# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not representable -.reloc a-a, R_X86_64_NONE, a -## TODO GNU as accepts x-x and y-x. -# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not representable +# ERR: {{.*}}.s:[[#@LINE+1]]:9: error: .reloc offset is not relative to a section +.reloc b-a, R_X86_64_NONE, a +# ERR: {{.*}}.s:[[#@LINE+1]]:9: error: .reloc offset is not relative to a section .reloc x-x, R_X86_64_NONE, a -# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: directional label undefined -.reloc 1f, R_X86_64_NONE, a .endif diff --git a/llvm/test/MC/Mips/reloc-directive-bad-obj.s b/llvm/test/MC/Mips/reloc-directive-bad-obj.s index 86d6d0cc66c57..74e5dae5264f6 100644 --- a/llvm/test/MC/Mips/reloc-directive-bad-obj.s +++ b/llvm/test/MC/Mips/reloc-directive-bad-obj.s @@ -2,8 +2,8 @@ # RUN: -target-abi=o32 -filetype=obj -o /dev/null 2>&1 | FileCheck %s .text nop -.reloc foo, R_MIPS_32, .text # CHECK: :[[@LINE]]:24: error: unresolved relocation offset +.reloc foo, R_MIPS_32, .text # CHECK: :[[@LINE]]:8: error: .reloc offset is not relative to a section nop nop -.reloc bar, R_MIPS_32, .text # CHECK: :[[@LINE]]:24: error: unresolved relocation offset +.reloc bar, R_MIPS_32, .text # CHECK: :[[@LINE]]:8: error: .reloc offset is not relative to a section nop diff --git a/llvm/test/MC/Mips/reloc-directive-label-offset.s b/llvm/test/MC/Mips/reloc-directive-label-offset.s index 257bfeb10d151..279fc7860dcea 100644 --- a/llvm/test/MC/Mips/reloc-directive-label-offset.s +++ b/llvm/test/MC/Mips/reloc-directive-label-offset.s @@ -58,18 +58,18 @@ bar: # OBJ-N32-LABEL: Relocations [ # OBJ-N32: 0x4 R_MIPS_NONE .text -# OBJ-N32-NEXT: 0x1C R_MIPS_GOT_OFST .text -# OBJ-N32-NEXT: 0x0 R_MIPS_32 .text # OBJ-N32-NEXT: 0xC R_MIPS_32 .text # OBJ-N32-NEXT: 0x10 R_MIPS_CALL16 foo # OBJ-N32-NEXT: 0x20 R_MIPS_GOT_DISP foo # OBJ-N32-NEXT: 0x24 R_MIPS_GOT_PAGE .text +# OBJ-N32-NEXT: 0x1C R_MIPS_GOT_OFST .text +# OBJ-N32-NEXT: 0x0 R_MIPS_32 .text # OBJ-N64-LABEL: Relocations [ # OBJ-N64: 0x4 R_MIPS_NONE/R_MIPS_NONE/R_MIPS_NONE .text 0x0 -# OBJ-N64-NEXT: 0x1C R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE .text 0x0 -# OBJ-N64-NEXT: 0x0 R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0 # OBJ-N64-NEXT: 0xC R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0 # OBJ-N64-NEXT: 0x10 R_MIPS_CALL16/R_MIPS_NONE/R_MIPS_NONE foo 0x0 # OBJ-N64-NEXT: 0x20 R_MIPS_GOT_DISP/R_MIPS_NONE/R_MIPS_NONE foo 0x0 # OBJ-N64-NEXT: 0x24 R_MIPS_GOT_PAGE/R_MIPS_NONE/R_MIPS_NONE .text 0x0 +# OBJ-N64-NEXT: 0x1C R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE .text 0x0 +# OBJ-N64-NEXT: 0x0 R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0 From 4fd2dd5b1a63f59aa7afbeb2fdfdf1d894603478 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 17 Jul 2025 10:29:18 -0700 Subject: [PATCH 06/39] MCAssembler: Modify Contents when VarFixups is not empty When there is no VarFixup, VarContentStart is zero. `slice(F.VarContentStart - Contents.size(), F.getSize())` might lead to "runtime error: addition of unsigned offset to" in ubsan builds after #148544 --- llvm/lib/MC/MCAssembler.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index f1a82f6b08d31..3e96bdf5169d8 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -735,13 +735,17 @@ void MCAssembler::layout() { // In the variable part, fixup offsets are relative to the fixed part's // start. Extend the variable contents to the left to account for the // fixed part size. - Contents = MutableArrayRef(F.getParent()->ContentStorage) - .slice(F.VarContentStart - Contents.size(), F.getSize()); - for (MCFixup &Fixup : F.getVarFixups()) { - uint64_t FixedValue; - MCValue Target; - evaluateFixup(F, Fixup, Target, FixedValue, - /*RecordReloc=*/true, Contents); + auto VarFixups = F.getVarFixups(); + if (VarFixups.size()) { + Contents = + MutableArrayRef(F.getParent()->ContentStorage) + .slice(F.VarContentStart - Contents.size(), F.getSize()); + for (MCFixup &Fixup : VarFixups) { + uint64_t FixedValue; + MCValue Target; + evaluateFixup(F, Fixup, Target, FixedValue, + /*RecordReloc=*/true, Contents); + } } } else if (auto *AF = dyn_cast(&F)) { // For RISC-V linker relaxation, an alignment relocation might be From 9e89cb76216088628056e70503c47b5acbb13c8c Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 18 Jul 2025 09:51:21 -0700 Subject: [PATCH 07/39] MC: Simplify fragment reuse determination First, avoid checking MCSubtargetInfo by reducing unnecessary overhead introduced in https://reviews.llvm.org/D44928 . That change passed STI to both FT_Data and FT_Relaxable fragments, but STI is only necessary for FT_Relaxable. The use of STI in FT_Data was added for: * Bundle alignment mode, which has been removed (#148781). * ARM, which inappropriately uses STI in `ARMAsmBackend::applyFixup` due to tech debt, unlike other targets. All tests passed even without the `copySTI` change. To ensure safety, `copySTI` now starts a new fragment to prevent mixed STI values. Second, avoid checking LinkerRelaxable by eagerly starting a new fragment when a FT_Data/FT_Align fragment is marked linker-relaxable. There is currently an extra empty FT_Data if an alignment immediately follows a linker-relaxable fragment, which will be improved in the future when FT_Align information is moved to the variable-tail. Pull Request: https://github.com/llvm/llvm-project/pull/149471 --- llvm/include/llvm/MC/MCObjectStreamer.h | 13 +------ llvm/include/llvm/MC/MCSection.h | 1 + llvm/include/llvm/MC/MCStreamer.h | 4 +- llvm/lib/MC/MCObjectStreamer.cpp | 43 ++++++++++------------ llvm/lib/MC/MCParser/MCTargetAsmParser.cpp | 5 +++ llvm/lib/MC/MCStreamer.cpp | 13 +++++++ llvm/test/MC/RISCV/Relocations/mc-dump.s | 1 + 7 files changed, 43 insertions(+), 37 deletions(-) diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index a55fd4a14675f..319e131999d48 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -73,20 +73,9 @@ class MCObjectStreamer : public MCStreamer { MCSymbol *emitCFILabel() override; void emitCFISections(bool EH, bool Debug) override; - void insert(MCFragment *F) { - auto *Sec = CurFrag->getParent(); - F->setParent(Sec); - F->setLayoutOrder(CurFrag->getLayoutOrder() + 1); - CurFrag->Next = F; - CurFrag = F; - Sec->curFragList()->Tail = F; - } - /// Get a data fragment to write into, creating a new one if the current /// fragment is not FT_Data. - /// Optionally a \p STI can be passed in so that a new fragment is created - /// if the Subtarget differs from the current fragment. - MCFragment *getOrCreateDataFragment(const MCSubtargetInfo *STI = nullptr); + MCFragment *getOrCreateDataFragment(); protected: bool changeSectionImpl(MCSection *Section, uint32_t Subsection); diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 28efe0a3b57d5..74d1ec37f068e 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -189,6 +189,7 @@ class LLVM_ABI MCSection { // destructors. class MCFragment { friend class MCAssembler; + friend class MCStreamer; friend class MCObjectStreamer; friend class MCSection; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 2cd621296ce76..2b0713f5df1cd 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -439,7 +439,6 @@ class LLVM_ABI MCStreamer { CurFrag->getParent() == getCurrentSection().first); return CurFrag; } - /// Save the current and previous section on the section stack. void pushSection() { SectionStack.push_back( @@ -467,6 +466,9 @@ class LLVM_ABI MCStreamer { MCSymbol *endSection(MCSection *Section); + void insert(MCFragment *F); + void newFragment(); + /// Returns the mnemonic for \p MI, if the streamer has access to a /// instruction printer and returns an empty string otherwise. virtual StringRef getMnemonic(const MCInst &MI) const { return ""; } diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 67433f2b265e5..d5b8f22463894 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -106,26 +106,12 @@ void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) { MCDwarfFrameEmitter::Emit(*this, MAB, false); } -static bool canReuseDataFragment(const MCFragment &F, - const MCAssembler &Assembler, - const MCSubtargetInfo *STI) { - if (!F.hasInstructions()) - return true; - // Do not add data after a linker-relaxable instruction. The difference - // between a new label and a label at or before the linker-relaxable - // instruction cannot be resolved at assemble-time. - if (F.isLinkerRelaxable()) - return false; - // If the subtarget is changed mid fragment we start a new fragment to record - // the new STI. - return !STI || F.getSubtargetInfo() == STI; -} - -MCFragment * -MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) { +MCFragment *MCObjectStreamer::getOrCreateDataFragment() { + // TODO: Start a new fragment whenever finalizing the variable-size tail of a + // previous one, so that all getOrCreateDataFragment calls can be replaced + // with getCurrentFragment auto *F = getCurrentFragment(); - if (F->getKind() != MCFragment::FT_Data || - !canReuseDataFragment(*F, *Assembler, STI)) { + if (F->getKind() != MCFragment::FT_Data) { F = getContext().allocFragment(); insert(F); } @@ -363,16 +349,23 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst, F->doneAppending(); if (!Fixups.empty()) F->appendFixups(Fixups); + F->setHasInstructions(STI); + bool MarkedLinkerRelaxable = false; for (auto &Fixup : MutableArrayRef(F->getFixups()).slice(FixupStartIndex)) { Fixup.setOffset(Fixup.getOffset() + CodeOffset); - if (Fixup.isLinkerRelaxable()) { - F->setLinkerRelaxable(); + if (!Fixup.isLinkerRelaxable()) + continue; + F->setLinkerRelaxable(); + // Do not add data after a linker-relaxable instruction. The difference + // between a new label and a label at or before the linker-relaxable + // instruction cannot be resolved at assemble-time. + if (!MarkedLinkerRelaxable) { + MarkedLinkerRelaxable = true; getCurrentSectionOnly()->setLinkerRelaxable(); + newFragment(); } } - - F->setHasInstructions(STI); } void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, @@ -568,8 +561,10 @@ void MCObjectStreamer::emitCodeAlignment(Align Alignment, // if the alignment is larger than the minimum NOP size. unsigned Size; if (getAssembler().getBackend().shouldInsertExtraNopBytesForCodeAlign(*F, - Size)) + Size)) { getCurrentSectionOnly()->setLinkerRelaxable(); + newFragment(); + } } void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, diff --git a/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp b/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp index 665d92eb9a21c..7f0934971b27c 100644 --- a/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp +++ b/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp @@ -9,6 +9,7 @@ #include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCRegister.h" +#include "llvm/MC/MCStreamer.h" using namespace llvm; @@ -22,6 +23,10 @@ MCTargetAsmParser::~MCTargetAsmParser() = default; MCSubtargetInfo &MCTargetAsmParser::copySTI() { MCSubtargetInfo &STICopy = getContext().getSubtargetCopy(getSTI()); STI = &STICopy; + // The returned STI will likely be modified. Create a new fragment to prevent + // mixing STI values within a fragment. + if (getStreamer().getCurrentFragment()) + getStreamer().newFragment(); return STICopy; } diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index d814ab8880500..c3ecf8fc717f5 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1404,6 +1404,19 @@ MCSymbol *MCStreamer::endSection(MCSection *Section) { return Sym; } +void MCStreamer::insert(MCFragment *F) { + auto *Sec = CurFrag->getParent(); + F->setParent(Sec); + F->setLayoutOrder(CurFrag->getLayoutOrder() + 1); + CurFrag->Next = F; + CurFrag = F; + Sec->curFragList()->Tail = F; +} + +void MCStreamer::newFragment() { + insert(getContext().allocFragment()); +} + static VersionTuple targetVersionOrMinimumSupportedOSVersion(const Triple &Target, VersionTuple TargetVersion) { diff --git a/llvm/test/MC/RISCV/Relocations/mc-dump.s b/llvm/test/MC/RISCV/Relocations/mc-dump.s index 24f3e67ebbdda..f72258498169f 100644 --- a/llvm/test/MC/RISCV/Relocations/mc-dump.s +++ b/llvm/test/MC/RISCV/Relocations/mc-dump.s @@ -9,6 +9,7 @@ # CHECK-NEXT:0 Data LinkerRelaxable Size:8 [97,00,00,00,e7,80,00,00] # CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023 # CHECK-NEXT: Symbol @0 $x +# CHECK-NEXT:8 Data Size:0 [] # CHECK-NEXT:8 Align Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops # CHECK-NEXT:12 Data Size:4 [13,05,30,00] # CHECK-NEXT:16 Align Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops From 7b6b5b5613197c43e99c4c2143b70270a19e9bd4 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 19 Jul 2025 09:59:27 -0700 Subject: [PATCH 08/39] MCFragment: Refactor LEB * Deduplicate creation of SLEB128/ULEB128 with makeLEB. * Call newFragment to prepare for removing getOrCreateDataFragment. --- llvm/include/llvm/MC/MCSection.h | 10 ++++++---- llvm/lib/MC/MCObjectStreamer.cpp | 10 ++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 74d1ec37f068e..66b2d8cd3fbb1 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -444,6 +444,12 @@ class MCFragment { } //== FT_LEB functions + void makeLEB(bool IsSigned, const MCExpr *Value) { + assert(Kind == FT_Data); + Kind = MCFragment::FT_LEB; + u.leb.IsSigned = IsSigned; + u.leb.Value = Value; + } const MCExpr &getLEBValue() const { assert(Kind == FT_LEB); return *u.leb.Value; @@ -456,10 +462,6 @@ class MCFragment { assert(Kind == FT_LEB); return u.leb.IsSigned; } - void setLEBSigned(bool S) { - assert(Kind == FT_LEB); - u.leb.IsSigned = S; - } //== FT_DwarfFrame functions const MCExpr &getDwarfAddrDelta() const { diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index d5b8f22463894..f61dda6d248b5 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -215,9 +215,8 @@ void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) { return; } auto *F = getOrCreateDataFragment(); - F->Kind = MCFragment::FT_LEB; - F->setLEBSigned(false); - F->setLEBValue(Value); + F->makeLEB(false, Value); + newFragment(); } void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) { @@ -227,9 +226,8 @@ void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) { return; } auto *F = getOrCreateDataFragment(); - F->Kind = MCFragment::FT_LEB; - F->setLEBSigned(true); - F->setLEBValue(Value); + F->makeLEB(true, Value); + newFragment(); } void MCObjectStreamer::emitWeakReference(MCSymbol *Alias, From 968a3e6306d431b86fc51b0ee7b12aed2a259ef9 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 19 Jul 2025 10:15:25 -0700 Subject: [PATCH 09/39] MC: Replace FT_PseudoProbe with FT_LEB The fragment type introduced by https://reviews.llvm.org/D91878 is unnecessary and can be replaced with FT_LEB. --- llvm/include/llvm/MC/MCAssembler.h | 3 --- llvm/include/llvm/MC/MCSection.h | 18 ------------------ llvm/lib/MC/MCAssembler.cpp | 22 +--------------------- llvm/lib/MC/MCFragment.cpp | 7 ------- llvm/lib/MC/MCPseudoProbe.cpp | 5 +++-- 5 files changed, 4 insertions(+), 51 deletions(-) diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index ade9ee6fa56e0..467ad4eabd3b0 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -36,8 +36,6 @@ class MCCVDefRangeFragment; class MCCVInlineLineTableFragment; class MCFragment; class MCFixup; -class MCLEBFragment; -class MCPseudoProbeAddrFragment; class MCSymbolRefExpr; class raw_ostream; class MCAsmBackend; @@ -123,7 +121,6 @@ class MCAssembler { bool relaxCVInlineLineTable(MCCVInlineLineTableFragment &DF); bool relaxCVDefRange(MCCVDefRangeFragment &DF); bool relaxFill(MCFillFragment &F); - bool relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &DF); public: /// Construct a new assembler instance. diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 66b2d8cd3fbb1..090300125ac4b 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -208,7 +208,6 @@ class MCFragment { FT_SymbolId, FT_CVInlineLines, FT_CVDefRange, - FT_PseudoProbe, }; private: @@ -288,7 +287,6 @@ class MCFragment { case MCFragment::FT_Dwarf: case MCFragment::FT_DwarfFrame: case MCFragment::FT_LEB: - case MCFragment::FT_PseudoProbe: case MCFragment::FT_CVInlineLines: case MCFragment::FT_CVDefRange: return true; @@ -733,22 +731,6 @@ class MCBoundaryAlignFragment : public MCFragment { } }; -class MCPseudoProbeAddrFragment : public MCEncodedFragment { - /// The expression for the difference of the two symbols that - /// make up the address delta between two .pseudoprobe directives. - const MCExpr *AddrDelta; - -public: - MCPseudoProbeAddrFragment(const MCExpr *AddrDelta) - : MCEncodedFragment(FT_PseudoProbe, false), AddrDelta(AddrDelta) {} - - const MCExpr &getAddrDelta() const { return *AddrDelta; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_PseudoProbe; - } -}; - inline MCSection::iterator &MCSection::iterator::operator++() { F = F->Next; return *this; diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 3e96bdf5169d8..942092457c452 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -201,7 +201,6 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const { case MCFragment::FT_DwarfFrame: case MCFragment::FT_CVInlineLines: case MCFragment::FT_CVDefRange: - case MCFragment::FT_PseudoProbe: return F.getSize(); case MCFragment::FT_Fill: { auto &FF = cast(F); @@ -424,8 +423,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, case MCFragment::FT_Dwarf: case MCFragment::FT_DwarfFrame: case MCFragment::FT_CVInlineLines: - case MCFragment::FT_CVDefRange: - case MCFragment::FT_PseudoProbe: { + case MCFragment::FT_CVDefRange: { if (F.getKind() == MCFragment::FT_Data) ++stats::EmittedDataFragments; else if (F.getKind() == MCFragment::FT_Relaxable) @@ -974,22 +972,6 @@ bool MCAssembler::relaxFill(MCFillFragment &F) { return true; } -bool MCAssembler::relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &PF) { - uint64_t OldSize = PF.getContents().size(); - int64_t AddrDelta; - bool Abs = PF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, *this); - assert(Abs && "We created a pseudo probe with an invalid expression"); - (void)Abs; - SmallVector Data; - raw_svector_ostream OSE(Data); - - // AddrDelta is a signed integer - encodeSLEB128(AddrDelta, OSE, OldSize); - PF.setContents(Data); - PF.clearFixups(); - return OldSize != Data.size(); -} - bool MCAssembler::relaxFragment(MCFragment &F) { switch(F.getKind()) { default: @@ -1011,8 +993,6 @@ bool MCAssembler::relaxFragment(MCFragment &F) { return relaxCVDefRange(cast(F)); case MCFragment::FT_Fill: return relaxFill(cast(F)); - case MCFragment::FT_PseudoProbe: - return relaxPseudoProbeAddr(cast(F)); } } diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index bfe045abe6e53..fe7afd4b41378 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -58,7 +58,6 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { case MCFragment::FT_SymbolId: OS << "SymbolId"; break; case MCFragment::FT_CVInlineLines: OS << "CVInlineLineTable"; break; case MCFragment::FT_CVDefRange: OS << "CVDefRangeTable"; break; - case MCFragment::FT_PseudoProbe: OS << "PseudoProbe"; break; // clang-format on } @@ -182,12 +181,6 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { } break; } - case MCFragment::FT_PseudoProbe: { - const auto *OF = cast(this); - OS << " AddrDelta:"; - OF->getAddrDelta().print(OS, nullptr); - break; - } } } #endif diff --git a/llvm/lib/MC/MCPseudoProbe.cpp b/llvm/lib/MC/MCPseudoProbe.cpp index f87d27f4adcc5..b493337b39317 100644 --- a/llvm/lib/MC/MCPseudoProbe.cpp +++ b/llvm/lib/MC/MCPseudoProbe.cpp @@ -81,8 +81,9 @@ void MCPseudoProbe::emit(MCObjectStreamer *MCOS, if (AddrDelta->evaluateAsAbsolute(Delta, MCOS->getAssemblerPtr())) { MCOS->emitSLEB128IntValue(Delta); } else { - MCOS->insert(MCOS->getContext().allocFragment( - AddrDelta)); + auto *F = MCOS->getCurrentFragment(); + F->makeLEB(true, AddrDelta); + MCOS->newFragment(); } } else { // Emit the GUID of the split function that the sentinel probe represents. From c6b6e16c1a1fb0e46fb082d734c42e824a7a3c7d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 19 Jul 2025 12:40:36 -0700 Subject: [PATCH 10/39] MCStreamer: Simplify with newFragment. NFC --- llvm/lib/MC/MCMachOStreamer.cpp | 2 +- llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index 13c1466d4d0ec..ad1fc3fccc440 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -163,7 +163,7 @@ void MCMachOStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { // We have to create a new fragment if this is an atom defining symbol, // fragments cannot span atoms. if (cast(Symbol)->isSymbolLinkerVisible()) - insert(getContext().allocFragment()); + newFragment(); MCObjectStreamer::emitLabel(Symbol, Loc); diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 3d060c6f4a780..387d289e36f8a 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -567,7 +567,7 @@ void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, // DataFragment, so that we can get the size of instructions later in // MCAssembler::relaxBoundaryAlign. The easiest way is to insert a new empty // DataFragment. - OS.insert(OS.getContext().allocFragment()); + OS.newFragment(); // Update the maximum alignment on the current section if necessary. MCSection *Sec = OS.getCurrentSectionOnly(); From 7e38cb1ce520683b87ad400eaec19a8cd9bc9039 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 19 Jul 2025 13:24:24 -0700 Subject: [PATCH 11/39] WasmObjectWrier: Simplify fragment walk in .init_array and reduce the reliance on the FT_Align/FT_Data layout, which will be changed by #149030 --- llvm/lib/MC/WasmObjectWriter.cpp | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 7af240a73f952..da6dbf3028f26 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -1858,23 +1858,9 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, auto IT = WS.begin(); if (IT == WS.end()) continue; - const MCFragment &EmptyFrag = *IT; - if (EmptyFrag.getKind() != MCFragment::FT_Data) - report_fatal_error(".init_array section should be aligned"); - - const MCFragment *nextFrag = EmptyFrag.getNext(); - while (nextFrag != nullptr) { - const MCFragment &AlignFrag = *nextFrag; - if (AlignFrag.getKind() != MCFragment::FT_Align) - report_fatal_error(".init_array section should be aligned"); - if (cast(AlignFrag).getAlignment() != - Align(is64Bit() ? 8 : 4)) - report_fatal_error( - ".init_array section should be aligned for pointers"); - - const MCFragment &Frag = *AlignFrag.getNext(); - nextFrag = Frag.getNext(); - if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) + for (auto *Frag = &*IT; Frag; Frag = Frag->getNext()) { + if (Frag->hasInstructions() || (Frag->getKind() != MCFragment::FT_Align && + Frag->getKind() != MCFragment::FT_Data)) report_fatal_error("only data supported in .init_array section"); uint16_t Priority = UINT16_MAX; @@ -1886,9 +1872,8 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority)) report_fatal_error("invalid .init_array section priority"); } - const auto &DataFrag = Frag; - assert(llvm::all_of(DataFrag.getContents(), [](char C) { return !C; })); - for (const MCFixup &Fixup : DataFrag.getFixups()) { + assert(llvm::all_of(Frag->getContents(), [](char C) { return !C; })); + for (const MCFixup &Fixup : Frag->getFixups()) { assert(Fixup.getKind() == MCFixup::getDataKindForSize(is64Bit() ? 8 : 4)); const MCExpr *Expr = Fixup.getValue(); From bb4cbd2b24ace1f06228bd7e8bfaa5c858a86eb3 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 19 Jul 2025 16:55:29 -0700 Subject: [PATCH 12/39] MC: Optimize getOrCreateDataFragment ... by eagerly allocating an empty fragment when adding a fragment with a variable-size tail. X86AsmBackend, The JCC erratum mitigation and x86-pad-for-align set a flag for FT_Relaxable, which needs to be moved to emitInstructionBegin. ``` if (CF->getKind() == MCFragment::FT_Relaxable) CF->setAllowAutoPadding(canPadInst(Inst, OS)); ``` Follow-up to #148544 --- llvm/include/llvm/MC/MCObjectStreamer.h | 8 ++-- llvm/include/llvm/MC/MCStreamer.h | 6 ++- llvm/lib/MC/MCCodeView.cpp | 4 +- llvm/lib/MC/MCObjectStreamer.cpp | 43 +++++++++---------- llvm/lib/MC/MCStreamer.cpp | 11 ++++- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 20 +++++---- 6 files changed, 52 insertions(+), 40 deletions(-) diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 319e131999d48..3ccc1e30222a9 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -73,12 +73,14 @@ class MCObjectStreamer : public MCStreamer { MCSymbol *emitCFILabel() override; void emitCFISections(bool EH, bool Debug) override; - /// Get a data fragment to write into, creating a new one if the current - /// fragment is not FT_Data. - MCFragment *getOrCreateDataFragment(); + // TODO: Change callers to use getCurrentFragment instead. + MCFragment *getOrCreateDataFragment() { return getCurrentFragment(); } protected: bool changeSectionImpl(MCSection *Section, uint32_t Subsection); + MCAlignFragment *createAlignFragment(Align Alignment, int64_t Fill, + uint8_t FillLen, + unsigned MaxBytesToEmit); public: void visitUsedSymbol(const MCSymbol &Sym) override; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 2b0713f5df1cd..b60082f4e8e17 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -273,6 +273,8 @@ class LLVM_ABI MCStreamer { /// section changes. virtual void changeSection(MCSection *, uint32_t); + void addFragment(MCFragment *F); + virtual void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame); virtual void emitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); @@ -466,8 +468,10 @@ class LLVM_ABI MCStreamer { MCSymbol *endSection(MCSection *Section); - void insert(MCFragment *F); + /// Add a new fragment to the current section without a variable-size tail. void newFragment(); + /// Add a fragment with a variable-size tail and start a new empty fragment. + void insert(MCFragment *F); /// Returns the mnemonic for \p MI, if the streamer has access to a /// instruction printer and returns an empty string otherwise. diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index 1f9825185175a..b151a2545ddb2 100644 --- a/llvm/lib/MC/MCCodeView.cpp +++ b/llvm/lib/MC/MCCodeView.cpp @@ -166,8 +166,8 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) { // somewhere else. If somebody wants two string tables in their .s file, one // will just be empty. if (!StrTabFragment) { - StrTabFragment = Ctx.allocFragment(); - OS.insert(StrTabFragment); + OS.newFragment(); + StrTabFragment = OS.getCurrentFragment(); } OS.emitValueToAlignment(Align(4), 0); diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index f61dda6d248b5..285c0f29ca4cc 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -106,18 +106,6 @@ void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) { MCDwarfFrameEmitter::Emit(*this, MAB, false); } -MCFragment *MCObjectStreamer::getOrCreateDataFragment() { - // TODO: Start a new fragment whenever finalizing the variable-size tail of a - // previous one, so that all getOrCreateDataFragment calls can be replaced - // with getCurrentFragment - auto *F = getCurrentFragment(); - if (F->getKind() != MCFragment::FT_Data) { - F = getContext().allocFragment(); - insert(F); - } - return F; -} - void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) { Assembler->registerSymbol(Sym); } @@ -379,6 +367,7 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, F->setVarContents(Data); F->setVarFixups(Fixups); F->setInst(Inst); + newFragment(); } void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, @@ -444,6 +433,7 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, F->Kind = MCFragment::FT_Dwarf; F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, SMLoc())); F->setDwarfLineDelta(LineDelta); + newFragment(); } void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section, @@ -474,6 +464,7 @@ void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, auto *F = getOrCreateDataFragment(); F->Kind = MCFragment::FT_DwarfFrame; F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, Loc)); + newFragment(); } void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo, @@ -536,32 +527,38 @@ void MCObjectStreamer::emitBytes(StringRef Data) { DF->appendContents(ArrayRef(Data.data(), Data.size())); } -void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill, - uint8_t FillLen, - unsigned MaxBytesToEmit) { +MCAlignFragment *MCObjectStreamer::createAlignFragment( + Align Alignment, int64_t Fill, uint8_t FillLen, unsigned MaxBytesToEmit) { if (MaxBytesToEmit == 0) MaxBytesToEmit = Alignment.value(); - insert(getContext().allocFragment(Alignment, Fill, FillLen, - MaxBytesToEmit)); + return getContext().allocFragment(Alignment, Fill, FillLen, + MaxBytesToEmit); +} +void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill, + uint8_t FillLen, + unsigned MaxBytesToEmit) { + auto *F = createAlignFragment(Alignment, Fill, FillLen, MaxBytesToEmit); + insert(F); // Update the maximum alignment on the current section if necessary. - MCSection *CurSec = getCurrentSectionOnly(); - CurSec->ensureMinAlignment(Alignment); + F->getParent()->ensureMinAlignment(Alignment); } void MCObjectStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit) { - emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit); - auto *F = cast(getCurrentFragment()); + auto *F = createAlignFragment(Alignment, 0, 1, MaxBytesToEmit); F->setEmitNops(true, STI); + insert(F); + // Update the maximum alignment on the current section if necessary. + F->getParent()->ensureMinAlignment(Alignment); + // With RISC-V style linker relaxation, mark the section as linker-relaxable // if the alignment is larger than the minimum NOP size. unsigned Size; if (getAssembler().getBackend().shouldInsertExtraNopBytesForCodeAlign(*F, Size)) { - getCurrentSectionOnly()->setLinkerRelaxable(); - newFragment(); + F->getParent()->setLinkerRelaxable(); } } diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index c3ecf8fc717f5..b0e52bf511ba4 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1404,7 +1404,7 @@ MCSymbol *MCStreamer::endSection(MCSection *Section) { return Sym; } -void MCStreamer::insert(MCFragment *F) { +void MCStreamer::addFragment(MCFragment *F) { auto *Sec = CurFrag->getParent(); F->setParent(Sec); F->setLayoutOrder(CurFrag->getLayoutOrder() + 1); @@ -1414,7 +1414,14 @@ void MCStreamer::insert(MCFragment *F) { } void MCStreamer::newFragment() { - insert(getContext().allocFragment()); + addFragment(getContext().allocFragment()); +} + +void MCStreamer::insert(MCFragment *F) { + assert(F->getKind() != MCFragment::FT_Data && + "F should have a variable-size tail"); + addFragment(F); + newFragment(); } static VersionTuple diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 387d289e36f8a..16de664d97f75 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -456,8 +456,6 @@ bool X86AsmBackend::canPadInst(const MCInst &Inst, MCObjectStreamer &OS) const { } bool X86AsmBackend::canPadBranches(MCObjectStreamer &OS) const { - if (!OS.getAllowAutoPadding()) - return false; assert(allowAutoPadding() && "incorrect initialization!"); // We only pad in text section. @@ -491,8 +489,15 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS, // fragment will have changed. IsRightAfterData = isRightAfterData(OS.getCurrentFragment(), PrevInstPosition); + bool CanPadInst = false; + bool AutoPadding = OS.getAllowAutoPadding(); + if (LLVM_UNLIKELY(AutoPadding || X86PadForAlign)) { + CanPadInst = canPadInst(Inst, OS); + if (CanPadInst) + OS.getCurrentFragment()->setAllowAutoPadding(true); + } - if (!canPadBranches(OS)) + if (!AutoPadding || !canPadBranches(OS)) return; // NB: PrevInst only valid if canPadBranches is true. @@ -504,7 +509,7 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS, // we call canPadInst (not cheap) twice. However, in the common case, we can // avoid unnecessary calls to that, as this is otherwise only used for // relaxable fragments. - if (!canPadInst(Inst, OS)) + if (!CanPadInst) return; if (PendingBA && PendingBA->getNext() == OS.getCurrentFragment()) { @@ -542,15 +547,12 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS, /// Set the last fragment to be aligned for the BoundaryAlignFragment. void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) { - MCFragment *CF = OS.getCurrentFragment(); - if (CF->getKind() == MCFragment::FT_Relaxable) - CF->setAllowAutoPadding(canPadInst(Inst, OS)); - // Update PrevInstOpcode here, canPadInst() reads that. + MCFragment *CF = OS.getCurrentFragment(); PrevInstOpcode = Inst.getOpcode(); PrevInstPosition = std::make_pair(CF, getSizeForInstFragment(CF)); - if (!canPadBranches(OS)) + if (!OS.getAllowAutoPadding() || !canPadBranches(OS)) return; // PrevInst is only needed if canPadBranches. Copying an MCInst isn't cheap. From 1583f31003a0ccf80c4b108cf8b93610062471cd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 19 Jul 2025 18:51:47 -0700 Subject: [PATCH 13/39] X86AsmBackend: Remove some overhead from auto padding feature MCObjectStreamer::emitInstructionImpl is hot. Devirtualize allowEnhancedRelaxation introduced by https://reviews.llvm.org/D76286 --- llvm/include/llvm/MC/MCAsmBackend.h | 7 ++- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 63 +++++++++---------- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index 62a5e013259df..2d709bdf8c65b 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -63,6 +63,9 @@ class LLVM_ABI MCAsmBackend { MCAssembler *Asm = nullptr; + bool AllowAutoPadding = false; + bool AllowEnhancedRelaxation = false; + public: MCAsmBackend(const MCAsmBackend &) = delete; MCAsmBackend &operator=(const MCAsmBackend &) = delete; @@ -76,11 +79,11 @@ class LLVM_ABI MCAsmBackend { /// Return true if this target might automatically pad instructions and thus /// need to emit padding enable/disable directives around sensative code. - virtual bool allowAutoPadding() const { return false; } + bool allowAutoPadding() const { return AllowAutoPadding; } /// Return true if this target allows an unrelaxable instruction to be /// emitted into RelaxableFragment and then we can increase its size in a /// tricky way for optimization. - virtual bool allowEnhancedRelaxation() const { return false; } + bool allowEnhancedRelaxation() const { return AllowEnhancedRelaxation; } /// lifetime management virtual void reset() {} diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 16de664d97f75..ad75ccd80b63d 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -127,7 +127,6 @@ class X86AsmBackend : public MCAsmBackend { unsigned PrevInstOpcode = 0; MCBoundaryAlignFragment *PendingBA = nullptr; std::pair PrevInstPosition; - bool IsRightAfterData = false; uint8_t determinePaddingPrefix(const MCInst &Inst) const; bool isMacroFused(const MCInst &Cmp, const MCInst &Jcc) const; @@ -156,10 +155,13 @@ class X86AsmBackend : public MCAsmBackend { AlignBranchType = X86AlignBranchKindLoc; if (X86PadMaxPrefixSize.getNumOccurrences()) TargetPrefixMax = X86PadMaxPrefixSize; + + AllowAutoPadding = + AlignBoundary != Align(1) && AlignBranchType != X86::AlignBranchNone; + AllowEnhancedRelaxation = + AllowAutoPadding && TargetPrefixMax != 0 && X86PadForBranchAlign; } - bool allowAutoPadding() const override; - bool allowEnhancedRelaxation() const override; void emitInstructionBegin(MCObjectStreamer &OS, const MCInst &Inst, const MCSubtargetInfo &STI); void emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst); @@ -365,14 +367,6 @@ static bool hasVariantSymbol(const MCInst &MI) { return false; } -bool X86AsmBackend::allowAutoPadding() const { - return (AlignBoundary != Align(1) && AlignBranchType != X86::AlignBranchNone); -} - -bool X86AsmBackend::allowEnhancedRelaxation() const { - return allowAutoPadding() && TargetPrefixMax != 0 && X86PadForBranchAlign; -} - /// X86 has certain instructions which enable interrupts exactly one /// instruction *after* the instruction which stores to SS. Return true if the /// given instruction may have such an interrupt delay slot. @@ -447,7 +441,7 @@ bool X86AsmBackend::canPadInst(const MCInst &Inst, MCObjectStreamer &OS) const { // semantic. return false; - if (IsRightAfterData) + if (isRightAfterData(OS.getCurrentFragment(), PrevInstPosition)) // If this instruction follows any data, there is no clear // instruction boundary, inserting a nop/prefix would change semantic. return false; @@ -456,6 +450,8 @@ bool X86AsmBackend::canPadInst(const MCInst &Inst, MCObjectStreamer &OS) const { } bool X86AsmBackend::canPadBranches(MCObjectStreamer &OS) const { + if (!OS.getAllowAutoPadding()) + return false; assert(allowAutoPadding() && "incorrect initialization!"); // We only pad in text section. @@ -482,22 +478,28 @@ bool X86AsmBackend::needAlign(const MCInst &Inst) const { (AlignBranchType & X86::AlignBranchIndirect)); } +void X86_MC::emitInstruction(MCObjectStreamer &S, const MCInst &Inst, + const MCSubtargetInfo &STI) { + bool AutoPadding = S.getAllowAutoPadding(); + if (LLVM_LIKELY(!AutoPadding && !X86PadForAlign)) { + S.MCObjectStreamer::emitInstruction(Inst, STI); + return; + } + + auto &Backend = static_cast(S.getAssembler().getBackend()); + Backend.emitInstructionBegin(S, Inst, STI); + S.MCObjectStreamer::emitInstruction(Inst, STI); + Backend.emitInstructionEnd(S, Inst); +} + /// Insert BoundaryAlignFragment before instructions to align branches. void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS, const MCInst &Inst, const MCSubtargetInfo &STI) { - // Used by canPadInst. Done here, because in emitInstructionEnd, the current - // fragment will have changed. - IsRightAfterData = - isRightAfterData(OS.getCurrentFragment(), PrevInstPosition); - bool CanPadInst = false; - bool AutoPadding = OS.getAllowAutoPadding(); - if (LLVM_UNLIKELY(AutoPadding || X86PadForAlign)) { - CanPadInst = canPadInst(Inst, OS); - if (CanPadInst) - OS.getCurrentFragment()->setAllowAutoPadding(true); - } + bool CanPadInst = canPadInst(Inst, OS); + if (CanPadInst) + OS.getCurrentFragment()->setAllowAutoPadding(true); - if (!AutoPadding || !canPadBranches(OS)) + if (!canPadBranches(OS)) return; // NB: PrevInst only valid if canPadBranches is true. @@ -552,7 +554,7 @@ void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, PrevInstOpcode = Inst.getOpcode(); PrevInstPosition = std::make_pair(CF, getSizeForInstFragment(CF)); - if (!OS.getAllowAutoPadding() || !canPadBranches(OS)) + if (!canPadBranches(OS)) return; // PrevInst is only needed if canPadBranches. Copying an MCInst isn't cheap. @@ -572,8 +574,7 @@ void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, OS.newFragment(); // Update the maximum alignment on the current section if necessary. - MCSection *Sec = OS.getCurrentSectionOnly(); - Sec->ensureMinAlignment(AlignBoundary); + CF->getParent()->ensureMinAlignment(AlignBoundary); } std::optional X86AsmBackend::getFixupKind(StringRef Name) const { @@ -1544,14 +1545,6 @@ class X86ELFStreamer : public MCELFStreamer { }; } // end anonymous namespace -void X86_MC::emitInstruction(MCObjectStreamer &S, const MCInst &Inst, - const MCSubtargetInfo &STI) { - auto &Backend = static_cast(S.getAssembler().getBackend()); - Backend.emitInstructionBegin(S, Inst, STI); - S.MCObjectStreamer::emitInstruction(Inst, STI); - Backend.emitInstructionEnd(S, Inst); -} - void X86ELFStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { X86_MC::emitInstruction(*this, Inst, STI); From 95084d6a1692d60d88e555b1f6be2cb9a0c70b06 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 20 Jul 2025 00:09:24 -0700 Subject: [PATCH 14/39] MC: Optimize emitInstruction and simplify fragment-in-BSS check Move the FT_Relaxable-in-BSS check from frequently-called MCObjectStreamer::emitInstruction to MCAssembler::writeSectionData, along with existing checks for other fragment types. For the uncommon diagnostics, losing the location information is acceptable. --- llvm/include/llvm/MC/MCObjectStreamer.h | 1 - llvm/lib/MC/MCAssembler.cpp | 41 +++++++----------------- llvm/lib/MC/MCObjectStreamer.cpp | 12 ------- llvm/lib/MC/WinCOFFObjectWriter.cpp | 11 ++++--- llvm/test/MC/COFF/bss-text.s | 12 ++++--- llvm/test/MC/COFF/section.s | 2 +- llvm/test/MC/ELF/nobits-non-zero-value.s | 16 +++++---- 7 files changed, 35 insertions(+), 60 deletions(-) diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 3ccc1e30222a9..deaabddab3cc7 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -54,7 +54,6 @@ class MCObjectStreamer : public MCStreamer { void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &); void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; - void emitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI); protected: MCObjectStreamer(MCContext &Context, std::unique_ptr TAB, diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 942092457c452..48b222e7ba5a9 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -583,42 +583,23 @@ void MCAssembler::writeSectionData(raw_ostream &OS, const MCSection *Sec) const { assert(getBackendPtr() && "Expected assembler backend"); - // Ignore virtual sections. if (Sec->isVirtualSection()) { assert(getSectionFileSize(*Sec) == 0 && "Invalid size for section!"); - // Check that contents are only things legal inside a virtual section. + // Ensure no fixups or non-zero bytes are written to BSS sections, catching + // errors in both input assembly code and MCStreamer API usage. Location is + // not tracked for efficiency. + auto Fn = [](char c) { return c != 0; }; for (const MCFragment &F : *Sec) { - switch (F.getKind()) { - default: llvm_unreachable("Invalid fragment in virtual section!"); - case MCFragment::FT_Data: { - // Check that we aren't trying to write a non-zero contents (or fixups) - // into a virtual section. This is to support clients which use standard - // directives to fill the contents of virtual sections. - if (F.getFixups().size() || F.getVarFixups().size()) - reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + - Sec->getName() + "' cannot have fixups"); - for (char C : F.getContents()) - if (C) { - reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + - Sec->getName() + - "' cannot have non-zero initializers"); - break; - } + if (any_of(F.getContents(), Fn) || any_of(F.getVarContents(), Fn)) { + reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + + Sec->getName() + + "' cannot have non-zero bytes"); break; } - case MCFragment::FT_Align: - // Check that we aren't trying to write a non-zero value into a virtual - // section. - assert((cast(F).getFillLen() == 0 || - cast(F).getFill() == 0) && - "Invalid align in virtual section!"); - break; - case MCFragment::FT_Fill: - assert((cast(F).getValue() == 0) && - "Invalid fill in virtual section!"); - break; - case MCFragment::FT_Org: + if (F.getFixups().size() || F.getVarFixups().size()) { + reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + + Sec->getName() + "' cannot have fixups"); break; } } diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 285c0f29ca4cc..739e5fec8aa5d 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -279,18 +279,6 @@ bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const { void MCObjectStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { - const MCSection &Sec = *getCurrentSectionOnly(); - if (Sec.isVirtualSection()) { - getContext().reportError(Inst.getLoc(), Twine(Sec.getVirtualSectionKind()) + - " section '" + Sec.getName() + - "' cannot have instructions"); - return; - } - emitInstructionImpl(Inst, STI); -} - -void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst, - const MCSubtargetInfo &STI) { MCStreamer::emitInstruction(Inst, STI); MCSection *Sec = getCurrentSectionOnly(); diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index ee4d957fe9d87..c69b8d669235f 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -179,7 +179,7 @@ class llvm::WinCOFFWriter { void SetSymbolName(COFFSymbol &S); void SetSectionName(COFFSection &S); - bool IsPhysicalSection(COFFSection *S); + bool isUninitializedData(const COFFSection &S); // Entity writing methods. void WriteFileHeader(const COFF::header &Header); @@ -453,8 +453,8 @@ void WinCOFFWriter::SetSymbolName(COFFSymbol &S) { std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size()); } -bool WinCOFFWriter::IsPhysicalSection(COFFSection *S) { - return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == +bool WinCOFFWriter::isUninitializedData(const COFFSection &S) { + return (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0; } @@ -606,6 +606,9 @@ void WinCOFFWriter::writeSection(const COFFSection &Sec) { assert(AuxSyms.size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition); AuxSymbol &SecDef = AuxSyms[0]; SecDef.Aux.SectionDefinition.CheckSum = CRC; + } else if (isUninitializedData(Sec)) { + // Error if fixups or non-zero bytes are present. + writeSectionContents(*Sec.MCSection); } // Write relocations for this section. @@ -745,7 +748,7 @@ void WinCOFFWriter::assignFileOffsets() { Sec->Header.SizeOfRawData = Asm->getSectionAddressSize(Section); - if (IsPhysicalSection(Sec)) { + if (!isUninitializedData(*Sec)) { Sec->Header.PointerToRawData = Offset; Offset += Sec->Header.SizeOfRawData; } diff --git a/llvm/test/MC/COFF/bss-text.s b/llvm/test/MC/COFF/bss-text.s index ed6890565b9a3..439bd789dff2c 100644 --- a/llvm/test/MC/COFF/bss-text.s +++ b/llvm/test/MC/COFF/bss-text.s @@ -1,13 +1,15 @@ -# RUN: not llvm-mc -filetype=obj -triple=x86_64-pc-win32 %s -o /dev/null 2>&1 | FileCheck %s +# RUN: not llvm-mc -filetype=obj -triple=x86_64-pc-win32 %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error: ## -filetype=asm does not check the error. # RUN: llvm-mc -triple=x86_64-pc-win32 %s +.bss +# CHECK: :0: error: IMAGE_SCN_CNT_UNINITIALIZED_DATA section '.bss' cannot have non-zero bytes + addb %bl,(%rax) + .section uninitialized,"b" -# MCRelaxableFragment -# CHECK: {{.*}}.s:[[#@LINE+1]]:3: error: IMAGE_SCN_CNT_UNINITIALIZED_DATA section 'uninitialized' cannot have instructions +# CHECK: :0: error: IMAGE_SCN_CNT_UNINITIALIZED_DATA section 'uninitialized' cannot have non-zero bytes jmp foo -.bss -# CHECK: {{.*}}.s:[[#@LINE+1]]:3: error: IMAGE_SCN_CNT_UNINITIALIZED_DATA section '.bss' cannot have instructions +.section bss0,"b" addb %al,(%rax) diff --git a/llvm/test/MC/COFF/section.s b/llvm/test/MC/COFF/section.s index 9c1a11effa341..fdd65701b1050 100644 --- a/llvm/test/MC/COFF/section.s +++ b/llvm/test/MC/COFF/section.s @@ -29,7 +29,7 @@ .section s ; .long 1 .section s_, "" ; .long 1 .section s_a,"a"; .long 1 -.section s_b,"b"; .long 1 +.section s_b,"b"; .long 0 .section s_d,"d"; .long 1 .section s_D,"D"; .long 1 .section s_n,"n"; .long 1 diff --git a/llvm/test/MC/ELF/nobits-non-zero-value.s b/llvm/test/MC/ELF/nobits-non-zero-value.s index ff43e69baaedc..e9516aa3e835a 100644 --- a/llvm/test/MC/ELF/nobits-non-zero-value.s +++ b/llvm/test/MC/ELF/nobits-non-zero-value.s @@ -1,26 +1,28 @@ -# RUN: not llvm-mc -filetype=obj -triple=x86_64 %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error: +# RUN: not llvm-mc -filetype=obj -triple=x86_64 %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error: --implicit-check-not=warning: ## -filetype=asm does not check the error. # RUN: llvm-mc -triple=x86_64 %s .section .tbss,"aw",@nobits -# MCRelaxableFragment -# CHECK: {{.*}}.s:[[#@LINE+1]]:3: error: SHT_NOBITS section '.tbss' cannot have instructions jmp foo .bss -# CHECK: {{.*}}.s:[[#@LINE+1]]:3: error: SHT_NOBITS section '.bss' cannot have instructions addb %al,(%rax) # CHECK: {{.*}}.s:[[#@LINE+1]]:11: warning: ignoring non-zero fill value in SHT_NOBITS section '.bss' .align 4, 42 -# CHECK-NOT: {{.*}}.s:[[#@LINE+1]]:11: warning: ignoring non-zero fill value in SHT_NOBITS section '.bss' .align 4, 0 -# CHECK: :0: error: SHT_NOBITS section '.bss' cannot have non-zero initializers .long 1 +.section .bss0,"aw",%nobits +addb %al,(%rax) + .section .bss1,"aw",%nobits -# CHECK: :0: error: SHT_NOBITS section '.bss1' cannot have fixups .quad foo + +## Location is not tracked for efficiency. +# CHECK: :0: error: SHT_NOBITS section '.tbss' cannot have non-zero bytes +# CHECK: :0: error: SHT_NOBITS section '.bss' cannot have non-zero bytes +# CHECK: :0: error: SHT_NOBITS section '.bss1' cannot have fixups From 1d923eafa694d08570d5bc55b71ebbb0694699f7 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 20 Jul 2025 00:46:51 -0700 Subject: [PATCH 15/39] MC: Encode FT_Align in fragment's variable-size tail Follow-up to #148544 Pull Request: https://github.com/llvm/llvm-project/pull/149030 --- llvm/include/llvm/MC/MCAsmBackend.h | 7 +- llvm/include/llvm/MC/MCObjectStreamer.h | 3 - llvm/include/llvm/MC/MCSection.h | 92 ++++++------ llvm/lib/MC/MCAssembler.cpp | 138 +++++++++--------- llvm/lib/MC/MCExpr.cpp | 8 +- llvm/lib/MC/MCFragment.cpp | 17 +-- llvm/lib/MC/MCObjectStreamer.cpp | 25 ++-- llvm/lib/MC/WasmObjectWriter.cpp | 19 ++- .../MCTargetDesc/LoongArchAsmBackend.cpp | 12 +- .../MCTargetDesc/LoongArchAsmBackend.h | 5 +- .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 8 +- .../RISCV/MCTargetDesc/RISCVAsmBackend.h | 5 +- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 4 +- llvm/test/MC/ELF/mc-dump.s | 8 +- llvm/test/MC/RISCV/Relocations/mc-dump.s | 12 +- 15 files changed, 170 insertions(+), 193 deletions(-) diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index 2d709bdf8c65b..b53db2d98b1f0 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -21,9 +21,7 @@ namespace llvm { -class MCAlignFragment; class MCFragment; -class MCLEBFragment; class MCSymbol; class MCAssembler; class MCContext; @@ -129,15 +127,14 @@ class LLVM_ABI MCAsmBackend { /// Hook to check if extra nop bytes must be inserted for alignment directive. /// For some targets this may be necessary in order to support linker /// relaxation. The number of bytes to insert are returned in Size. - virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF, + virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF, unsigned &Size) { return false; } /// Hook which indicates if the target requires a fixup to be generated when /// handling an align directive in an executable section - virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, - MCAlignFragment &AF) { + virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF) { return false; } diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index deaabddab3cc7..633334ee8a33f 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -77,9 +77,6 @@ class MCObjectStreamer : public MCStreamer { protected: bool changeSectionImpl(MCSection *Section, uint32_t Subsection); - MCAlignFragment *createAlignFragment(Align Alignment, int64_t Fill, - uint8_t FillLen, - unsigned MaxBytesToEmit); public: void visitUsedSymbol(const MCSymbol &Sym) override; diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 090300125ac4b..02abb280f95fd 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -255,6 +255,19 @@ class MCFragment { uint32_t OperandStart; uint32_t OperandSize; } relax; + struct { + // The alignment to ensure, in bytes. + Align Alignment; + // The size of the integer (in bytes) of \p Value. + uint8_t FillLen; + // If true, fill with target-specific nop instructions. + bool EmitNops; + // The maximum number of bytes to emit; if the alignment + // cannot be satisfied in this width then this fragment is ignored. + unsigned MaxBytesToEmit; + // Value to use for filling padding bytes. + int64_t Fill; + } align; struct { // True if this is a sleb128, false if uleb128. bool IsSigned; @@ -284,6 +297,7 @@ class MCFragment { return false; case MCFragment::FT_Relaxable: case MCFragment::FT_Data: + case MCFragment::FT_Align: case MCFragment::FT_Dwarf: case MCFragment::FT_DwarfFrame: case MCFragment::FT_LEB: @@ -441,6 +455,38 @@ class MCFragment { llvm::copy(Inst, S.begin() + u.relax.OperandStart); } + //== FT_Align functions + void makeAlign(Align Alignment, int64_t Fill, uint8_t FillLen, + unsigned MaxBytesToEmit) { + Kind = FT_Align; + u.align.EmitNops = false; + u.align.Alignment = Alignment; + u.align.Fill = Fill; + u.align.FillLen = FillLen; + u.align.MaxBytesToEmit = MaxBytesToEmit; + } + + Align getAlignment() const { + assert(Kind == FT_Align); + return u.align.Alignment; + } + int64_t getAlignFill() const { + assert(Kind == FT_Align); + return u.align.Fill; + } + uint8_t getAlignFillLen() const { + assert(Kind == FT_Align); + return u.align.FillLen; + } + unsigned getAlignMaxBytesToEmit() const { + assert(Kind == FT_Align); + return u.align.MaxBytesToEmit; + } + bool hasAlignEmitNops() const { + assert(Kind == FT_Align); + return u.align.EmitNops; + } + //== FT_LEB functions void makeLEB(bool IsSigned, const MCExpr *Value) { assert(Kind == FT_Data); @@ -488,52 +534,6 @@ class MCEncodedFragment : public MCFragment { : MCFragment(FType, HasInstructions) {} }; -class MCAlignFragment : public MCFragment { - /// Flag to indicate that (optimal) NOPs should be emitted instead - /// of using the provided value. The exact interpretation of this flag is - /// target dependent. - bool EmitNops : 1; - - /// The alignment to ensure, in bytes. - Align Alignment; - - /// The size of the integer (in bytes) of \p Value. - uint8_t FillLen; - - /// The maximum number of bytes to emit; if the alignment - /// cannot be satisfied in this width then this fragment is ignored. - unsigned MaxBytesToEmit; - - /// Value to use for filling padding bytes. - int64_t Fill; - - /// When emitting Nops some subtargets have specific nop encodings. - const MCSubtargetInfo *STI = nullptr; - -public: - MCAlignFragment(Align Alignment, int64_t Fill, uint8_t FillLen, - unsigned MaxBytesToEmit) - : MCFragment(FT_Align, false), EmitNops(false), Alignment(Alignment), - FillLen(FillLen), MaxBytesToEmit(MaxBytesToEmit), Fill(Fill) {} - - Align getAlignment() const { return Alignment; } - int64_t getFill() const { return Fill; } - uint8_t getFillLen() const { return FillLen; } - unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } - - bool hasEmitNops() const { return EmitNops; } - void setEmitNops(bool Value, const MCSubtargetInfo *STI) { - EmitNops = Value; - this->STI = STI; - } - - const MCSubtargetInfo *getSubtargetInfo() const { return STI; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Align; - } -}; - class MCFillFragment : public MCFragment { uint8_t ValueSize; /// Value to use for filling bytes. diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 48b222e7ba5a9..3ab402a8e2832 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -227,25 +227,24 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const { return 4; case MCFragment::FT_Align: { - const MCAlignFragment &AF = cast(F); - unsigned Offset = getFragmentOffset(AF); - unsigned Size = offsetToAlignment(Offset, AF.getAlignment()); + unsigned Offset = F.Offset + F.getFixedSize(); + unsigned Size = offsetToAlignment(Offset, F.getAlignment()); // Insert extra Nops for code alignment if the target define // shouldInsertExtraNopBytesForCodeAlign target hook. - if (AF.getParent()->useCodeAlign() && AF.hasEmitNops() && - getBackend().shouldInsertExtraNopBytesForCodeAlign(AF, Size)) - return Size; + if (F.getParent()->useCodeAlign() && F.hasAlignEmitNops() && + getBackend().shouldInsertExtraNopBytesForCodeAlign(F, Size)) + return F.getFixedSize() + Size; // If we are padding with nops, force the padding to be larger than the // minimum nop size. - if (Size > 0 && AF.hasEmitNops()) { + if (Size > 0 && F.hasAlignEmitNops()) { while (Size % getBackend().getMinimumNopSize()) - Size += AF.getAlignment().value(); + Size += F.getAlignment().value(); } - if (Size > AF.getMaxBytesToEmit()) - return 0; - return Size; + if (Size > F.getAlignMaxBytesToEmit()) + Size = 0; + return F.getFixedSize() + Size; } case MCFragment::FT_Org: { @@ -419,6 +418,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, switch (F.getKind()) { case MCFragment::FT_Data: case MCFragment::FT_Relaxable: + case MCFragment::FT_Align: case MCFragment::FT_LEB: case MCFragment::FT_Dwarf: case MCFragment::FT_DwarfFrame: @@ -431,48 +431,46 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, const auto &EF = cast(F); OS << StringRef(EF.getContents().data(), EF.getContents().size()); OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size()); - break; - } - case MCFragment::FT_Align: { - ++stats::EmittedAlignFragments; - const MCAlignFragment &AF = cast(F); - assert(AF.getFillLen() && "Invalid virtual align in concrete fragment!"); - - uint64_t Count = FragmentSize / AF.getFillLen(); - assert(FragmentSize % AF.getFillLen() == 0 && - "computeFragmentSize computed size is incorrect"); - - // See if we are aligning with nops, and if so do that first to try to fill - // the Count bytes. Then if that did not fill any bytes or there are any - // bytes left to fill use the Value and ValueSize to fill the rest. - // If we are aligning with nops, ask that target to emit the right data. - if (AF.hasEmitNops()) { - if (!Asm.getBackend().writeNopData(OS, Count, AF.getSubtargetInfo())) - report_fatal_error("unable to write nop sequence of " + - Twine(Count) + " bytes"); - break; - } - - // Otherwise, write out in multiples of the value size. - for (uint64_t i = 0; i != Count; ++i) { - switch (AF.getFillLen()) { - default: llvm_unreachable("Invalid size!"); - case 1: - OS << char(AF.getFill()); - break; - case 2: - support::endian::write(OS, AF.getFill(), Endian); - break; - case 4: - support::endian::write(OS, AF.getFill(), Endian); - break; - case 8: - support::endian::write(OS, AF.getFill(), Endian); - break; + if (F.getKind() == MCFragment::FT_Align) { + ++stats::EmittedAlignFragments; + assert(F.getAlignFillLen() && + "Invalid virtual align in concrete fragment!"); + + uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen(); + assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 && + "computeFragmentSize computed size is incorrect"); + + // See if we are aligning with nops, and if so do that first to try to + // fill the Count bytes. Then if that did not fill any bytes or there are + // any bytes left to fill use the Value and ValueSize to fill the rest. If + // we are aligning with nops, ask that target to emit the right data. + if (F.hasAlignEmitNops()) { + if (!Asm.getBackend().writeNopData(OS, Count, F.getSubtargetInfo())) + report_fatal_error("unable to write nop sequence of " + Twine(Count) + + " bytes"); + } else { + // Otherwise, write out in multiples of the value size. + for (uint64_t i = 0; i != Count; ++i) { + switch (F.getAlignFillLen()) { + default: + llvm_unreachable("Invalid size!"); + case 1: + OS << char(F.getAlignFill()); + break; + case 2: + support::endian::write(OS, F.getAlignFill(), Endian); + break; + case 4: + support::endian::write(OS, F.getAlignFill(), Endian); + break; + case 8: + support::endian::write(OS, F.getAlignFill(), Endian); + break; + } + } } } - break; - } + } break; case MCFragment::FT_Fill: { ++stats::EmittedFillFragments; @@ -703,34 +701,30 @@ void MCAssembler::layout() { for (MCSection &Sec : *this) { for (MCFragment &F : Sec) { // Process fragments with fixups here. - if (F.isEncoded()) { - auto Contents = F.getContents(); - for (MCFixup &Fixup : F.getFixups()) { + auto Contents = F.getContents(); + for (MCFixup &Fixup : F.getFixups()) { + uint64_t FixedValue; + MCValue Target; + evaluateFixup(F, Fixup, Target, FixedValue, + /*RecordReloc=*/true, Contents); + } + if (F.getVarFixups().size()) { + // In the variable part, fixup offsets are relative to the fixed part's + // start. Extend the variable contents to the left to account for the + // fixed part size. + Contents = MutableArrayRef(F.getParent()->ContentStorage) + .slice(F.VarContentStart - Contents.size(), F.getSize()); + for (MCFixup &Fixup : F.getVarFixups()) { uint64_t FixedValue; MCValue Target; evaluateFixup(F, Fixup, Target, FixedValue, /*RecordReloc=*/true, Contents); } - // In the variable part, fixup offsets are relative to the fixed part's - // start. Extend the variable contents to the left to account for the - // fixed part size. - auto VarFixups = F.getVarFixups(); - if (VarFixups.size()) { - Contents = - MutableArrayRef(F.getParent()->ContentStorage) - .slice(F.VarContentStart - Contents.size(), F.getSize()); - for (MCFixup &Fixup : VarFixups) { - uint64_t FixedValue; - MCValue Target; - evaluateFixup(F, Fixup, Target, FixedValue, - /*RecordReloc=*/true, Contents); - } - } - } else if (auto *AF = dyn_cast(&F)) { + } else if (F.getKind() == MCFragment::FT_Align) { // For RISC-V linker relaxation, an alignment relocation might be // needed. - if (AF->hasEmitNops()) - getBackend().shouldInsertFixupForCodeAlign(*this, *AF); + if (F.hasAlignEmitNops()) + getBackend().shouldInsertFixupForCodeAlign(*this, F); } } } diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index 22dff497911de..f0f1bd485258f 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -379,11 +379,11 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, // After layout, during relocation generation, it can be treated as a // data fragment. Displacement += F->getSize(); - } else if (auto *AF = dyn_cast(F); - AF && Layout && AF->hasEmitNops() && + } else if (F->getKind() == MCFragment::FT_Align && Layout && + F->hasAlignEmitNops() && !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign( - *AF, Count)) { - Displacement += Asm->computeFragmentSize(*AF); + *F, Count)) { + Displacement += Asm->computeFragmentSize(*F); } else if (auto *FF = dyn_cast(F); FF && FF->getNumValues().evaluateAsAbsolute(Num)) { Displacement += Num * FF->getValueSize(); diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index fe7afd4b41378..569f2a5652869 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -72,17 +72,9 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { }; switch (getKind()) { - case MCFragment::FT_Align: { - const auto *AF = cast(this); - OS << " Align:" << AF->getAlignment().value() << " Fill:" << AF->getFill() - << " FillLen:" << unsigned(AF->getFillLen()) - << " MaxBytesToEmit:" << AF->getMaxBytesToEmit(); - if (AF->hasEmitNops()) - OS << " Nops"; - break; - } case MCFragment::FT_Data: case MCFragment::FT_Relaxable: + case MCFragment::FT_Align: case MCFragment::FT_LEB: case MCFragment::FT_Dwarf: case MCFragment::FT_DwarfFrame: { @@ -111,6 +103,13 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { OS << ' '; getInst().dump_pretty(OS); break; + case MCFragment::FT_Align: + OS << "\n Align:" << getAlignment().value() << " Fill:" << getAlignFill() + << " FillLen:" << unsigned(getAlignFillLen()) + << " MaxBytesToEmit:" << getAlignMaxBytesToEmit(); + if (hasAlignEmitNops()) + OS << " Nops"; + break; case MCFragment::FT_LEB: { OS << " Value:"; getLEBValue().print(OS, nullptr); diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 739e5fec8aa5d..af47df2967bb3 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -515,19 +515,15 @@ void MCObjectStreamer::emitBytes(StringRef Data) { DF->appendContents(ArrayRef(Data.data(), Data.size())); } -MCAlignFragment *MCObjectStreamer::createAlignFragment( - Align Alignment, int64_t Fill, uint8_t FillLen, unsigned MaxBytesToEmit) { - if (MaxBytesToEmit == 0) - MaxBytesToEmit = Alignment.value(); - return getContext().allocFragment(Alignment, Fill, FillLen, - MaxBytesToEmit); -} - void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill, uint8_t FillLen, unsigned MaxBytesToEmit) { - auto *F = createAlignFragment(Alignment, Fill, FillLen, MaxBytesToEmit); - insert(F); + if (MaxBytesToEmit == 0) + MaxBytesToEmit = Alignment.value(); + MCFragment *F = getCurrentFragment(); + F->makeAlign(Alignment, Fill, FillLen, MaxBytesToEmit); + newFragment(); + // Update the maximum alignment on the current section if necessary. F->getParent()->ensureMinAlignment(Alignment); } @@ -535,11 +531,10 @@ void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill, void MCObjectStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit) { - auto *F = createAlignFragment(Alignment, 0, 1, MaxBytesToEmit); - F->setEmitNops(true, STI); - insert(F); - // Update the maximum alignment on the current section if necessary. - F->getParent()->ensureMinAlignment(Alignment); + auto *F = getCurrentFragment(); + emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit); + F->u.align.EmitNops = true; + F->STI = STI; // With RISC-V style linker relaxation, mark the section as linker-relaxable // if the alignment is larger than the minimum NOP size. diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index da6dbf3028f26..3b99af47eb45b 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -696,14 +696,15 @@ static void addData(SmallVectorImpl &DataBytes, if (Frag.hasInstructions()) report_fatal_error("only data supported in data sections"); - if (auto *Align = dyn_cast(&Frag)) { - if (Align->getFillLen() != 1) + llvm::append_range(DataBytes, Frag.getContents()); + if (Frag.getKind() == MCFragment::FT_Align) { + if (Frag.getAlignFillLen() != 1) report_fatal_error("only byte values supported for alignment"); // If nops are requested, use zeros, as this is the data section. - uint8_t Value = Align->hasEmitNops() ? 0 : Align->getFill(); + uint8_t Value = Frag.hasAlignEmitNops() ? 0 : Frag.getAlignFill(); uint64_t Size = - std::min(alignTo(DataBytes.size(), Align->getAlignment()), - DataBytes.size() + Align->getMaxBytesToEmit()); + std::min(alignTo(DataBytes.size(), Frag.getAlignment()), + DataBytes.size() + Frag.getAlignMaxBytesToEmit()); DataBytes.resize(Size, Value); } else if (auto *Fill = dyn_cast(&Frag)) { int64_t NumValues; @@ -711,12 +712,10 @@ static void addData(SmallVectorImpl &DataBytes, llvm_unreachable("The fill should be an assembler constant"); DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues, Fill->getValue()); + } else if (Frag.getKind() == MCFragment::FT_LEB) { + llvm::append_range(DataBytes, Frag.getVarContents()); } else { - llvm::append_range(DataBytes, Frag.getContents()); - if (Frag.getKind() == MCFragment::FT_LEB) - llvm::append_range(DataBytes, Frag.getVarContents()); - else - assert(Frag.getKind() == MCFragment::FT_Data); + assert(Frag.getKind() == MCFragment::FT_Data); } } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp index 7b9f1156f9102..032bfea71140f 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -182,14 +182,14 @@ void LoongArchAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup, // could satisfy alignment by removing Nops. // The function returns the total Nops Size we need to insert. bool LoongArchAsmBackend::shouldInsertExtraNopBytesForCodeAlign( - const MCAlignFragment &AF, unsigned &Size) { + const MCFragment &AF, unsigned &Size) { // Calculate Nops Size only when linker relaxation enabled. if (!AF.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax)) return false; // Ignore alignment if MaxBytesToEmit is less than the minimum Nop size. const unsigned MinNopLen = 4; - if (AF.getMaxBytesToEmit() < MinNopLen) + if (AF.getAlignMaxBytesToEmit() < MinNopLen) return false; Size = AF.getAlignment().value() - MinNopLen; return AF.getAlignment() > MinNopLen; @@ -205,7 +205,7 @@ bool LoongArchAsmBackend::shouldInsertExtraNopBytesForCodeAlign( // maximum number of bytes to emit. The maximum number of bytes is zero // means ignore the emit limit. bool LoongArchAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm, - MCAlignFragment &AF) { + MCFragment &AF) { // Insert the fixup only when linker relaxation enabled. if (!AF.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax)) return false; @@ -219,8 +219,8 @@ bool LoongArchAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCSection *Sec = AF.getParent(); MCContext &Ctx = getContext(); const MCExpr *Dummy = MCConstantExpr::create(0, Ctx); - MCFixup Fixup = MCFixup::create(0, Dummy, ELF::R_LARCH_ALIGN); - unsigned MaxBytesToEmit = AF.getMaxBytesToEmit(); + MCFixup Fixup = MCFixup::create(AF.getFixedSize(), Dummy, ELF::R_LARCH_ALIGN); + unsigned MaxBytesToEmit = AF.getAlignMaxBytesToEmit(); auto createExtendedValue = [&]() { const MCSymbolRefExpr *MCSym = getSecToAlignSym()[Sec]; @@ -434,7 +434,7 @@ bool LoongArchAsmBackend::isPCRelFixupResolved(const MCSymbol *SymA, // Otherwise, check if the offset between the symbol and fragment is fully // resolved, unaffected by linker-relaxable fragments (e.g. instructions or - // offset-affected MCAlignFragment). Complements the generic + // offset-affected FT_Align fragments). Complements the generic // isSymbolRefDifferenceFullyResolvedImpl. if (!PCRelTemp) PCRelTemp = getContext().createTempSymbol(); diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h index b32ba067810ce..793e4093b1c9e 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h @@ -46,12 +46,11 @@ class LoongArchAsmBackend : public MCAsmBackend { bool IsResolved) override; // Return Size with extra Nop Bytes for alignment directive in code section. - bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF, + bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF, unsigned &Size) override; // Insert target specific fixup type for alignment directive in code section. - bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, - MCAlignFragment &AF) override; + bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF) override; bool shouldForceRelocation(const MCFixup &Fixup, const MCValue &Target); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index f76f8b3060d2a..6bc313656f7c1 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -637,7 +637,7 @@ bool RISCVAsmBackend::isPCRelFixupResolved(const MCSymbol *SymA, // Otherwise, check if the offset between the symbol and fragment is fully // resolved, unaffected by linker-relaxable fragments (e.g. instructions or - // offset-affected MCAlignFragment). Complements the generic + // offset-affected FT_Align fragments). Complements the generic // isSymbolRefDifferenceFullyResolvedImpl. if (!PCRelTemp) PCRelTemp = getContext().createTempSymbol(); @@ -892,7 +892,7 @@ void RISCVAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup, // could satisfy alignment by removing Nops. // The function return the total Nops Size we need to insert. bool RISCVAsmBackend::shouldInsertExtraNopBytesForCodeAlign( - const MCAlignFragment &AF, unsigned &Size) { + const MCFragment &AF, unsigned &Size) { // Calculate Nops Size only when linker relaxation enabled. const MCSubtargetInfo *STI = AF.getSubtargetInfo(); if (!STI->hasFeature(RISCV::FeatureRelax)) @@ -914,7 +914,7 @@ bool RISCVAsmBackend::shouldInsertExtraNopBytesForCodeAlign( // The function insert fixup_riscv_align fixup which eventually will // transfer to R_RISCV_ALIGN relocation type. bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm, - MCAlignFragment &AF) { + MCFragment &AF) { // Insert the fixup only when linker relaxation enabled. const MCSubtargetInfo *STI = AF.getSubtargetInfo(); if (!STI->hasFeature(RISCV::FeatureRelax)) @@ -928,7 +928,7 @@ bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCContext &Ctx = getContext(); const MCExpr *Dummy = MCConstantExpr::create(0, Ctx); - MCFixup Fixup = MCFixup::create(0, Dummy, ELF::R_RISCV_ALIGN); + MCFixup Fixup = MCFixup::create(AF.getFixedSize(), Dummy, ELF::R_RISCV_ALIGN); uint64_t FixedValue = 0; MCValue NopBytes = MCValue::get(Count); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index 8c10fbec3c8fc..c4a1c74aa2c54 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -39,12 +39,11 @@ class RISCVAsmBackend : public MCAsmBackend { ~RISCVAsmBackend() override = default; // Return Size with extra Nop Bytes for alignment directive in code section. - bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF, + bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF, unsigned &Size) override; // Insert target specific fixup type for alignment directive in code section. - bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, - MCAlignFragment &AF) override; + bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF) override; std::optional evaluateFixup(const MCFragment &, MCFixup &, MCValue &, uint64_t &) override; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index ad75ccd80b63d..e213923ccf38e 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -926,13 +926,11 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const { continue; } - const uint64_t OrigSize = Asm.computeFragmentSize(F); - // To keep the effects local, prefer to relax instructions closest to // the align directive. This is purely about human understandability // of the resulting code. If we later find a reason to expand // particular instructions over others, we can adjust. - unsigned RemainingSize = OrigSize; + unsigned RemainingSize = Asm.computeFragmentSize(F) - F.getFixedSize(); while (!Relaxable.empty() && RemainingSize != 0) { auto &RF = *Relaxable.pop_back_val(); // Give the backend a chance to play any tricks it wishes to increase diff --git a/llvm/test/MC/ELF/mc-dump.s b/llvm/test/MC/ELF/mc-dump.s index 5cc2e9fa50179..fd6cf95f4af44 100644 --- a/llvm/test/MC/ELF/mc-dump.s +++ b/llvm/test/MC/ELF/mc-dump.s @@ -6,9 +6,9 @@ #CHECK-LABEL:assembler backend - final-layout # CHECK:Sections:[ # CHECK-NEXT:MCSection Name:.text -# CHECK-NEXT:0 Data Size:0 [] +# CHECK-NEXT:0 Align Size:0+0 [] +# CHECK-NEXT: Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 Nops # CHECK-NEXT: Symbol @0 .text -# CHECK-NEXT:0 Align Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 Nops # CHECK-NEXT:0 Data Size:0 [] # CHECK-NEXT: Symbol @0 _start # CHECK-NEXT: Symbol @0 Temporary @@ -22,9 +22,9 @@ # CHECK-NEXT: Symbol @0 Temporary # CHECK-NEXT: Symbol @16 Temporary # CHECK-NEXT:MCSection Name:.data -# CHECK-NEXT:0 Data Size:0 [] +# CHECK-NEXT:0 Align Size:0+0 [] +# CHECK-NEXT: Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 # CHECK-NEXT: Symbol @0 .data -# CHECK-NEXT:0 Align Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 # CHECK-NEXT:0 Data Size:4 [01,00,00,00] # CHECK-NEXT:4 Fill Value:0 ValueSize:1 NumValues:1 # CHECK-NEXT:5 LEB Size:0+1 [15] Value:.Ltmp0-_start Signed:0 diff --git a/llvm/test/MC/RISCV/Relocations/mc-dump.s b/llvm/test/MC/RISCV/Relocations/mc-dump.s index f72258498169f..842851ce04843 100644 --- a/llvm/test/MC/RISCV/Relocations/mc-dump.s +++ b/llvm/test/MC/RISCV/Relocations/mc-dump.s @@ -3,16 +3,16 @@ # CHECK:Sections:[ # CHECK-NEXT:MCSection Name:.text -# CHECK-NEXT:0 Data Size:0 [] +# CHECK-NEXT:0 Align Size:0+0 [] +# CHECK-NEXT: Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 Nops # CHECK-NEXT: Symbol @0 .text -# CHECK-NEXT:0 Align Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 Nops # CHECK-NEXT:0 Data LinkerRelaxable Size:8 [97,00,00,00,e7,80,00,00] # CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023 # CHECK-NEXT: Symbol @0 $x -# CHECK-NEXT:8 Data Size:0 [] -# CHECK-NEXT:8 Align Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops -# CHECK-NEXT:12 Data Size:4 [13,05,30,00] -# CHECK-NEXT:16 Align Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops +# CHECK-NEXT:8 Align Size:0+0 [] +# CHECK-NEXT: Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops +# CHECK-NEXT:12 Align Size:4+0 [13,05,30,00] +# CHECK-NEXT: Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops # CHECK-NEXT:] call ext From fa3395eb54cae02674d87085582fd7b777df4145 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 20 Jul 2025 00:55:54 -0700 Subject: [PATCH 16/39] MC: Refactor FT_Align fragments when linker relaxation is enabled Previously, two MCAsmBackend hooks were used, with shouldInsertFixupForCodeAlign calling getWriter().recordRelocation directly, bypassing generic code. This patch: * Introduces MCAsmBackend::relaxAlign to replace the two hooks. * Tracks padding size using VarContentEnd (content is ignored). * Move setLinkerRelaxable from MCObjectStreamer::emitCodeAlignment to the backends. Pull Request: https://github.com/llvm/llvm-project/pull/149465 --- llvm/include/llvm/MC/MCAsmBackend.h | 18 +-- llvm/lib/MC/MCAssembler.cpp | 126 +++++++++--------- llvm/lib/MC/MCExpr.cpp | 5 +- llvm/lib/MC/MCFragment.cpp | 7 +- llvm/lib/MC/MCObjectStreamer.cpp | 8 -- .../MCTargetDesc/LoongArchAsmBackend.cpp | 115 +++++++--------- .../MCTargetDesc/LoongArchAsmBackend.h | 8 +- .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 71 +++------- .../RISCV/MCTargetDesc/RISCVAsmBackend.h | 8 +- llvm/test/MC/RISCV/Relocations/mc-dump.s | 6 +- 10 files changed, 148 insertions(+), 224 deletions(-) diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index b53db2d98b1f0..03dc14736396d 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -124,20 +124,6 @@ class LLVM_ABI MCAsmBackend { /// Get information on a fixup kind. virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const; - /// Hook to check if extra nop bytes must be inserted for alignment directive. - /// For some targets this may be necessary in order to support linker - /// relaxation. The number of bytes to insert are returned in Size. - virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF, - unsigned &Size) { - return false; - } - - /// Hook which indicates if the target requires a fixup to be generated when - /// handling an align directive in an executable section - virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF) { - return false; - } - // Evaluate a fixup, returning std::nullopt to use default handling for // `Value` and `IsResolved`. Otherwise, returns `IsResolved` with the // expectation that the hook updates `Value`. @@ -195,6 +181,10 @@ class LLVM_ABI MCAsmBackend { } // Defined by linker relaxation targets. + + // Return false to use default handling. Otherwise, set `Size` to the number + // of padding bytes. + virtual bool relaxAlign(MCFragment &F, unsigned &Size) { return false; } virtual bool relaxDwarfLineAddr(MCFragment &, bool &WasRelaxed) const { return false; } diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 3ab402a8e2832..674adc92257c9 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -196,6 +196,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const { switch (F.getKind()) { case MCFragment::FT_Data: case MCFragment::FT_Relaxable: + case MCFragment::FT_Align: case MCFragment::FT_LEB: case MCFragment::FT_Dwarf: case MCFragment::FT_DwarfFrame: @@ -226,27 +227,6 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const { case MCFragment::FT_SymbolId: return 4; - case MCFragment::FT_Align: { - unsigned Offset = F.Offset + F.getFixedSize(); - unsigned Size = offsetToAlignment(Offset, F.getAlignment()); - - // Insert extra Nops for code alignment if the target define - // shouldInsertExtraNopBytesForCodeAlign target hook. - if (F.getParent()->useCodeAlign() && F.hasAlignEmitNops() && - getBackend().shouldInsertExtraNopBytesForCodeAlign(F, Size)) - return F.getFixedSize() + Size; - - // If we are padding with nops, force the padding to be larger than the - // minimum nop size. - if (Size > 0 && F.hasAlignEmitNops()) { - while (Size % getBackend().getMinimumNopSize()) - Size += F.getAlignment().value(); - } - if (Size > F.getAlignMaxBytesToEmit()) - Size = 0; - return F.getFixedSize() + Size; - } - case MCFragment::FT_Org: { const MCOrgFragment &OF = cast(F); MCValue Value; @@ -418,7 +398,6 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, switch (F.getKind()) { case MCFragment::FT_Data: case MCFragment::FT_Relaxable: - case MCFragment::FT_Align: case MCFragment::FT_LEB: case MCFragment::FT_Dwarf: case MCFragment::FT_DwarfFrame: @@ -431,42 +410,41 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, const auto &EF = cast(F); OS << StringRef(EF.getContents().data(), EF.getContents().size()); OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size()); - if (F.getKind() == MCFragment::FT_Align) { - ++stats::EmittedAlignFragments; - assert(F.getAlignFillLen() && - "Invalid virtual align in concrete fragment!"); - - uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen(); - assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 && - "computeFragmentSize computed size is incorrect"); - - // See if we are aligning with nops, and if so do that first to try to - // fill the Count bytes. Then if that did not fill any bytes or there are - // any bytes left to fill use the Value and ValueSize to fill the rest. If - // we are aligning with nops, ask that target to emit the right data. - if (F.hasAlignEmitNops()) { - if (!Asm.getBackend().writeNopData(OS, Count, F.getSubtargetInfo())) - report_fatal_error("unable to write nop sequence of " + Twine(Count) + - " bytes"); - } else { - // Otherwise, write out in multiples of the value size. - for (uint64_t i = 0; i != Count; ++i) { - switch (F.getAlignFillLen()) { - default: - llvm_unreachable("Invalid size!"); - case 1: - OS << char(F.getAlignFill()); - break; - case 2: - support::endian::write(OS, F.getAlignFill(), Endian); - break; - case 4: - support::endian::write(OS, F.getAlignFill(), Endian); - break; - case 8: - support::endian::write(OS, F.getAlignFill(), Endian); - break; - } + } break; + + case MCFragment::FT_Align: { + ++stats::EmittedAlignFragments; + OS << StringRef(F.getContents().data(), F.getContents().size()); + assert(F.getAlignFillLen() && + "Invalid virtual align in concrete fragment!"); + + uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen(); + assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 && + "computeFragmentSize computed size is incorrect"); + + // In the nops mode, call the backend hook to write `Count` nops. + if (F.hasAlignEmitNops()) { + if (!Asm.getBackend().writeNopData(OS, Count, F.getSubtargetInfo())) + reportFatalInternalError("unable to write nop sequence of " + + Twine(Count) + " bytes"); + } else { + // Otherwise, write out in multiples of the value size. + for (uint64_t i = 0; i != Count; ++i) { + switch (F.getAlignFillLen()) { + default: + llvm_unreachable("Invalid size!"); + case 1: + OS << char(F.getAlignFill()); + break; + case 2: + support::endian::write(OS, F.getAlignFill(), Endian); + break; + case 4: + support::endian::write(OS, F.getAlignFill(), Endian); + break; + case 8: + support::endian::write(OS, F.getAlignFill(), Endian); + break; } } } @@ -720,11 +698,6 @@ void MCAssembler::layout() { evaluateFixup(F, Fixup, Target, FixedValue, /*RecordReloc=*/true, Contents); } - } else if (F.getKind() == MCFragment::FT_Align) { - // For RISC-V linker relaxation, an alignment relocation might be - // needed. - if (F.hasAlignEmitNops()) - getBackend().shouldInsertFixupForCodeAlign(*this, F); } } } @@ -975,7 +948,32 @@ void MCAssembler::layoutSection(MCSection &Sec) { uint64_t Offset = 0; for (MCFragment &F : Sec) { F.Offset = Offset; - Offset += computeFragmentSize(F); + if (F.getKind() == MCFragment::FT_Align) { + Offset += F.getFixedSize(); + unsigned Size = offsetToAlignment(Offset, F.getAlignment()); + // In the nops mode, RISC-V style linker relaxation might adjust the size + // and add a fixup, even if `Size` is originally 0. + bool AlignFixup = false; + if (F.hasAlignEmitNops()) { + AlignFixup = getBackend().relaxAlign(F, Size); + // If the backend does not handle the fragment specially, pad with nops, + // but ensure that the padding is larger than the minimum nop size. + if (!AlignFixup) + while (Size % getBackend().getMinimumNopSize()) + Size += F.getAlignment().value(); + } + if (!AlignFixup && Size > F.getAlignMaxBytesToEmit()) + Size = 0; + // Update the variable tail size. The content is ignored. + assert(F.VarContentStart == 0 && + "VarContentStart should not be modified"); + F.VarContentEnd = Size; + if (F.VarContentEnd > F.getParent()->ContentStorage.size()) + F.getParent()->ContentStorage.resize(F.VarContentEnd); + Offset += Size; + } else { + Offset += computeFragmentSize(F); + } } } diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index f0f1bd485258f..dbb2fd16eb2e5 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -370,7 +370,6 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, } int64_t Num; - unsigned Count; if (DF) { Displacement += DF->getContents().size(); } else if (F->getKind() == MCFragment::FT_Relaxable && @@ -380,9 +379,7 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, // data fragment. Displacement += F->getSize(); } else if (F->getKind() == MCFragment::FT_Align && Layout && - F->hasAlignEmitNops() && - !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign( - *F, Count)) { + F->isLinkerRelaxable()) { Displacement += Asm->computeFragmentSize(*F); } else if (auto *FF = dyn_cast(F); FF && FF->getNumValues().evaluateAsAbsolute(Num)) { diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index 569f2a5652869..3c395e5ccdb0b 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -83,8 +83,13 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { auto Fixed = getContents(); auto Var = getVarContents(); OS << " Size:" << Fixed.size(); - if (getKind() != MCFragment::FT_Data) + if (getKind() != MCFragment::FT_Data) { OS << '+' << Var.size(); + // FT_Align uses getVarContents to track the size, but the content is + // ignored and not useful. + if (getKind() == MCFragment::FT_Align) + Var = {}; + } OS << " ["; for (unsigned i = 0, e = Fixed.size(); i != e; ++i) { if (i) OS << ","; diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index af47df2967bb3..83e447abb7e06 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -535,14 +535,6 @@ void MCObjectStreamer::emitCodeAlignment(Align Alignment, emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit); F->u.align.EmitNops = true; F->STI = STI; - - // With RISC-V style linker relaxation, mark the section as linker-relaxable - // if the alignment is larger than the minimum NOP size. - unsigned Size; - if (getAssembler().getBackend().shouldInsertExtraNopBytesForCodeAlign(*F, - Size)) { - F->getParent()->setLinkerRelaxable(); - } } void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp index 032bfea71140f..8fa72bc9a30a7 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -177,74 +177,6 @@ void LoongArchAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup, } } -// Linker relaxation may change code size. We have to insert Nops -// for .align directive when linker relaxation enabled. So then Linker -// could satisfy alignment by removing Nops. -// The function returns the total Nops Size we need to insert. -bool LoongArchAsmBackend::shouldInsertExtraNopBytesForCodeAlign( - const MCFragment &AF, unsigned &Size) { - // Calculate Nops Size only when linker relaxation enabled. - if (!AF.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax)) - return false; - - // Ignore alignment if MaxBytesToEmit is less than the minimum Nop size. - const unsigned MinNopLen = 4; - if (AF.getAlignMaxBytesToEmit() < MinNopLen) - return false; - Size = AF.getAlignment().value() - MinNopLen; - return AF.getAlignment() > MinNopLen; -} - -// We need to insert R_LARCH_ALIGN relocation type to indicate the -// position of Nops and the total bytes of the Nops have been inserted -// when linker relaxation enabled. -// The function inserts fixup_loongarch_align fixup which eventually will -// transfer to R_LARCH_ALIGN relocation type. -// The improved R_LARCH_ALIGN requires symbol index. The lowest 8 bits of -// addend represent alignment and the other bits of addend represent the -// maximum number of bytes to emit. The maximum number of bytes is zero -// means ignore the emit limit. -bool LoongArchAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm, - MCFragment &AF) { - // Insert the fixup only when linker relaxation enabled. - if (!AF.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax)) - return false; - - // Calculate total Nops we need to insert. If there are none to insert - // then simply return. - unsigned InsertedNopBytes; - if (!shouldInsertExtraNopBytesForCodeAlign(AF, InsertedNopBytes)) - return false; - - MCSection *Sec = AF.getParent(); - MCContext &Ctx = getContext(); - const MCExpr *Dummy = MCConstantExpr::create(0, Ctx); - MCFixup Fixup = MCFixup::create(AF.getFixedSize(), Dummy, ELF::R_LARCH_ALIGN); - unsigned MaxBytesToEmit = AF.getAlignMaxBytesToEmit(); - - auto createExtendedValue = [&]() { - const MCSymbolRefExpr *MCSym = getSecToAlignSym()[Sec]; - if (MCSym == nullptr) { - // Define a marker symbol at the section with an offset of 0. - MCSymbol *Sym = Ctx.createNamedTempSymbol("la-relax-align"); - Sym->setFragment(&*Sec->getBeginSymbol()->getFragment()); - Asm.registerSymbol(*Sym); - MCSym = MCSymbolRefExpr::create(Sym, Ctx); - getSecToAlignSym()[Sec] = MCSym; - } - return MCValue::get(&MCSym->getSymbol(), nullptr, - MaxBytesToEmit << 8 | Log2(AF.getAlignment())); - }; - - uint64_t FixedValue = 0; - MCValue Value = MaxBytesToEmit >= InsertedNopBytes - ? MCValue::get(InsertedNopBytes) - : createExtendedValue(); - Asm.getWriter().recordRelocation(AF, Fixup, Value, FixedValue); - - return true; -} - bool LoongArchAsmBackend::shouldForceRelocation(const MCFixup &Fixup, const MCValue &Target) { switch (Fixup.getKind()) { @@ -279,6 +211,53 @@ getRelocPairForSize(unsigned Size) { } } +// Check if an R_LARCH_ALIGN relocation is needed for an alignment directive. +// If conditions are met, compute the padding size and create a fixup encoding +// the padding size in the addend. If MaxBytesToEmit is smaller than the padding +// size, the fixup encodes MaxBytesToEmit in the higher bits and references a +// per-section marker symbol. +bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) { + // Use default handling unless linker relaxation is enabled and the + // MaxBytesToEmit >= the nop size. + if (!F.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax)) + return false; + const unsigned MinNopLen = 4; + unsigned MaxBytesToEmit = F.getAlignMaxBytesToEmit(); + if (MaxBytesToEmit < MinNopLen) + return false; + + Size = F.getAlignment().value() - MinNopLen; + if (F.getAlignment() <= MinNopLen) + return false; + + MCContext &Ctx = getContext(); + const MCExpr *Expr = nullptr; + if (MaxBytesToEmit >= Size) { + Expr = MCConstantExpr::create(Size, getContext()); + } else { + MCSection *Sec = F.getParent(); + const MCSymbolRefExpr *SymRef = getSecToAlignSym()[Sec]; + if (SymRef == nullptr) { + // Define a marker symbol at the section with an offset of 0. + MCSymbol *Sym = Ctx.createNamedTempSymbol("la-relax-align"); + Sym->setFragment(&*Sec->getBeginSymbol()->getFragment()); + Asm->registerSymbol(*Sym); + SymRef = MCSymbolRefExpr::create(Sym, Ctx); + getSecToAlignSym()[Sec] = SymRef; + } + Expr = MCBinaryExpr::createAdd( + SymRef, + MCConstantExpr::create((MaxBytesToEmit << 8) | Log2(F.getAlignment()), + Ctx), + Ctx); + } + MCFixup Fixup = + MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN); + F.setVarFixups({Fixup}); + F.getParent()->setLinkerRelaxable(); + return true; +} + std::pair LoongArchAsmBackend::relaxLEB128(MCFragment &F, int64_t &Value) const { const MCExpr &Expr = F.getLEBValue(); diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h index 793e4093b1c9e..3d929fc49f95e 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h @@ -45,19 +45,13 @@ class LoongArchAsmBackend : public MCAsmBackend { MutableArrayRef Data, uint64_t Value, bool IsResolved) override; - // Return Size with extra Nop Bytes for alignment directive in code section. - bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF, - unsigned &Size) override; - - // Insert target specific fixup type for alignment directive in code section. - bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF) override; - bool shouldForceRelocation(const MCFixup &Fixup, const MCValue &Target); std::optional getFixupKind(StringRef Name) const override; MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override; + bool relaxAlign(MCFragment &F, unsigned &Size) override; bool relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const override; bool relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const override; std::pair relaxLEB128(MCFragment &F, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index 6bc313656f7c1..2c37c3bfd0fe3 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -302,6 +302,28 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst, Inst = std::move(Res); } +// Check if an R_RISCV_ALIGN relocation is needed for an alignment directive. +// If conditions are met, compute the padding size and create a fixup encoding +// the padding size in the addend. +bool RISCVAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) { + // Use default handling unless linker relaxation is enabled and the alignment + // is larger than the nop size. + const MCSubtargetInfo *STI = F.getSubtargetInfo(); + if (!STI->hasFeature(RISCV::FeatureRelax)) + return false; + unsigned MinNopLen = STI->hasFeature(RISCV::FeatureStdExtZca) ? 2 : 4; + if (F.getAlignment() <= MinNopLen) + return false; + + Size = F.getAlignment().value() - MinNopLen; + auto *Expr = MCConstantExpr::create(Size, getContext()); + MCFixup Fixup = + MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_RISCV_ALIGN); + F.setVarFixups({Fixup}); + F.getParent()->setLinkerRelaxable(); + return true; +} + bool RISCVAsmBackend::relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const { MCContext &C = getContext(); @@ -887,55 +909,6 @@ void RISCVAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup, } } -// Linker relaxation may change code size. We have to insert Nops -// for .align directive when linker relaxation enabled. So then Linker -// could satisfy alignment by removing Nops. -// The function return the total Nops Size we need to insert. -bool RISCVAsmBackend::shouldInsertExtraNopBytesForCodeAlign( - const MCFragment &AF, unsigned &Size) { - // Calculate Nops Size only when linker relaxation enabled. - const MCSubtargetInfo *STI = AF.getSubtargetInfo(); - if (!STI->hasFeature(RISCV::FeatureRelax)) - return false; - - unsigned MinNopLen = STI->hasFeature(RISCV::FeatureStdExtZca) ? 2 : 4; - - if (AF.getAlignment() <= MinNopLen) { - return false; - } else { - Size = AF.getAlignment().value() - MinNopLen; - return true; - } -} - -// We need to insert R_RISCV_ALIGN relocation type to indicate the -// position of Nops and the total bytes of the Nops have been inserted -// when linker relaxation enabled. -// The function insert fixup_riscv_align fixup which eventually will -// transfer to R_RISCV_ALIGN relocation type. -bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm, - MCFragment &AF) { - // Insert the fixup only when linker relaxation enabled. - const MCSubtargetInfo *STI = AF.getSubtargetInfo(); - if (!STI->hasFeature(RISCV::FeatureRelax)) - return false; - - // Calculate total Nops we need to insert. If there are none to insert - // then simply return. - unsigned Count; - if (!shouldInsertExtraNopBytesForCodeAlign(AF, Count) || (Count == 0)) - return false; - - MCContext &Ctx = getContext(); - const MCExpr *Dummy = MCConstantExpr::create(0, Ctx); - MCFixup Fixup = MCFixup::create(AF.getFixedSize(), Dummy, ELF::R_RISCV_ALIGN); - - uint64_t FixedValue = 0; - MCValue NopBytes = MCValue::get(Count); - Asm.getWriter().recordRelocation(AF, Fixup, NopBytes, FixedValue); - return true; -} - std::unique_ptr RISCVAsmBackend::createObjectTargetWriter() const { return createRISCVELFObjectWriter(OSABI, Is64Bit); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index c4a1c74aa2c54..d97d63204e7e4 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -38,13 +38,6 @@ class RISCVAsmBackend : public MCAsmBackend { const MCTargetOptions &Options); ~RISCVAsmBackend() override = default; - // Return Size with extra Nop Bytes for alignment directive in code section. - bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF, - unsigned &Size) override; - - // Insert target specific fixup type for alignment directive in code section. - bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF) override; - std::optional evaluateFixup(const MCFragment &, MCFixup &, MCValue &, uint64_t &) override; bool addReloc(const MCFragment &, const MCFixup &, const MCValue &, @@ -72,6 +65,7 @@ class RISCVAsmBackend : public MCAsmBackend { void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; + bool relaxAlign(MCFragment &F, unsigned &Size) override; bool relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const override; bool relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const override; std::pair relaxLEB128(MCFragment &LF, diff --git a/llvm/test/MC/RISCV/Relocations/mc-dump.s b/llvm/test/MC/RISCV/Relocations/mc-dump.s index 842851ce04843..e8f4b14ce3725 100644 --- a/llvm/test/MC/RISCV/Relocations/mc-dump.s +++ b/llvm/test/MC/RISCV/Relocations/mc-dump.s @@ -9,10 +9,12 @@ # CHECK-NEXT:0 Data LinkerRelaxable Size:8 [97,00,00,00,e7,80,00,00] # CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023 # CHECK-NEXT: Symbol @0 $x -# CHECK-NEXT:8 Align Size:0+0 [] +# CHECK-NEXT:8 Align Size:0+4 [] # CHECK-NEXT: Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops -# CHECK-NEXT:12 Align Size:4+0 [13,05,30,00] +# CHECK-NEXT: Fixup @0 Value:4 Kind:[[#]] +# CHECK-NEXT:12 Align Size:4+4 [13,05,30,00] # CHECK-NEXT: Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops +# CHECK-NEXT: Fixup @4 Value:4 Kind:[[#]] # CHECK-NEXT:] call ext From 96f121aff6d85ccfedb604395964f813256f5207 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 20 Jul 2025 10:39:16 -0700 Subject: [PATCH 17/39] MC: Rename isVirtualSection to isBssSection The term BSS (Block Started by Symbol) is a standard, widely recognized term, available in the a.out object file format and adopted by formats like COFF, XCOFF, Mach-O (called S_ZEROFILL while `__bss` is also used), and ELF. To avoid introducing unfamiliar terms, we should use isBSSSection instead of isVirtualSection. --- llvm/include/llvm/MC/MCSection.h | 9 ++++----- llvm/include/llvm/MC/MCSectionGOFF.h | 2 +- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +- llvm/lib/MC/MCAssembler.cpp | 4 ++-- llvm/lib/MC/MCMachOStreamer.cpp | 2 +- llvm/lib/MC/MCParser/AsmParser.cpp | 2 +- llvm/lib/MC/MCSection.cpp | 2 +- llvm/lib/MC/MachObjectWriter.cpp | 12 ++++++------ llvm/lib/ObjCopy/MachO/MachOObject.h | 4 ++-- llvm/lib/ObjCopy/MachO/MachOWriter.cpp | 4 ++-- 10 files changed, 21 insertions(+), 22 deletions(-) diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 02abb280f95fd..22786bde75773 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -92,8 +92,7 @@ class LLVM_ABI MCSection { bool IsRegistered : 1; bool IsText : 1; - - bool IsVirtual : 1; + bool IsBss : 1; /// Whether the section contains linker-relaxable fragments. If true, the /// offset between two locations may not be fully resolved. @@ -177,9 +176,9 @@ class LLVM_ABI MCSection { /// instead of 0s. virtual bool useCodeAlign() const = 0; - /// Check whether this section is "virtual", that is has no actual object - /// file contents. - bool isVirtualSection() const { return IsVirtual; } + /// Return true if this is a BSS section (e.g., ELF .bss or .tbss) that does + /// not store content and is typically initialized to zeroes by the runtime. + bool isBssSection() const { return IsBss; } virtual StringRef getVirtualSectionKind() const; }; diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h index 9e3f95e82a14c..b166397b5d370 100644 --- a/llvm/include/llvm/MC/MCSectionGOFF.h +++ b/llvm/include/llvm/MC/MCSectionGOFF.h @@ -111,7 +111,7 @@ class LLVM_ABI MCSectionGOFF final : public MCSection { // Returns the text style for a section. Only defined for ED and PR sections. GOFF::ESDTextStyle getTextStyle() const { - assert((isED() || isPR() || isVirtualSection()) && "Expect ED or PR section"); + assert((isED() || isPR() || isBssSection()) && "Expect ED or PR section"); if (isED()) return EDAttributes.TextStyle; if (isPR()) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index be0a1c3b0a0c2..4f00c8e7b4127 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -810,7 +810,7 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { // If we have a bss global going to a section that supports the // zerofill directive, do so here. - if (GVKind.isBSS() && MAI->isMachO() && TheSection->isVirtualSection()) { + if (GVKind.isBSS() && MAI->isMachO() && TheSection->isBssSection()) { if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined. emitLinkage(GV, GVSym); diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 674adc92257c9..317ba8128cff1 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -362,7 +362,7 @@ uint64_t MCAssembler::getSectionAddressSize(const MCSection &Sec) const { uint64_t MCAssembler::getSectionFileSize(const MCSection &Sec) const { // Virtual sections have no file size. - if (Sec.isVirtualSection()) + if (Sec.isBssSection()) return 0; return getSectionAddressSize(Sec); } @@ -559,7 +559,7 @@ void MCAssembler::writeSectionData(raw_ostream &OS, const MCSection *Sec) const { assert(getBackendPtr() && "Expected assembler backend"); - if (Sec->isVirtualSection()) { + if (Sec->isBssSection()) { assert(getSectionFileSize(*Sec) == 0 && "Invalid size for section!"); // Ensure no fixups or non-zero bytes are written to BSS sections, catching diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index ad1fc3fccc440..4d76299f3c821 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -401,7 +401,7 @@ void MCMachOStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, // On darwin all virtual sections have zerofill type. Disallow the usage of // .zerofill in non-virtual functions. If something similar is needed, use // .space or .zero. - if (!Section->isVirtualSection()) { + if (!Section->isBssSection()) { getContext().reportError( Loc, "The usage of .zerofill is restricted to sections of " "ZEROFILL type. Use .zero or .space instead."); diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 77bf84364c5a3..4c55e97f0c1fc 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -3404,7 +3404,7 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, uint8_t ValueSize) { const MCSection *Section = getStreamer().getCurrentSectionOnly(); assert(Section && "must have section to emit alignment"); - if (HasFillExpr && FillExpr != 0 && Section->isVirtualSection()) { + if (HasFillExpr && FillExpr != 0 && Section->isBssSection()) { ReturnVal |= Warning(FillExprLoc, "ignoring non-zero fill value in " + Section->getVirtualSectionKind() + diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index 93671450c0c2f..fd1d072cf4152 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -21,7 +21,7 @@ using namespace llvm; MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText, bool IsVirtual, MCSymbol *Begin) : Begin(Begin), HasInstructions(false), IsRegistered(false), IsText(IsText), - IsVirtual(IsVirtual), LinkerRelaxable(false), Name(Name), Variant(V) { + IsBss(IsVirtual), LinkerRelaxable(false), Name(Name), Variant(V) { // The initial subsection number is 0. Create a fragment list. CurFragList = &Subsections.emplace_back(0u, FragList{}).second; } diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp index 9250375962732..34a7f6c4afab1 100644 --- a/llvm/lib/MC/MachObjectWriter.cpp +++ b/llvm/lib/MC/MachObjectWriter.cpp @@ -134,7 +134,7 @@ uint64_t MachObjectWriter::getPaddingSize(const MCAssembler &Asm, return 0; const MCSection &NextSec = *SectionOrder[Next]; - if (NextSec.isVirtualSection()) + if (NextSec.isBssSection()) return 0; return offsetToAlignment(EndAddr, NextSec.getAlign()); } @@ -277,7 +277,7 @@ void MachObjectWriter::writeSection(const MCAssembler &Asm, const MCSectionMachO &Section = cast(Sec); // The offset is unused for virtual sections. - if (Section.isVirtualSection()) { + if (Section.isBssSection()) { assert(Asm.getSectionFileSize(Sec) == 0 && "Invalid file size!"); FileOffset = 0; } @@ -692,13 +692,13 @@ void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm) { unsigned i = 0; // Compute the section layout order. Virtual sections must go last. for (MCSection &Sec : Asm) { - if (!Sec.isVirtualSection()) { + if (!Sec.isBssSection()) { SectionOrder.push_back(&Sec); cast(Sec).setLayoutOrder(i++); } } for (MCSection &Sec : Asm) { - if (Sec.isVirtualSection()) { + if (Sec.isBssSection()) { SectionOrder.push_back(&Sec); cast(Sec).setLayoutOrder(i++); } @@ -895,7 +895,7 @@ void MachObjectWriter::writeMachOHeader(MCAssembler &Asm) { VMSize = std::max(VMSize, Address + Size); - if (Sec.isVirtualSection()) + if (Sec.isBssSection()) continue; SectionDataSize = std::max(SectionDataSize, Address + Size); @@ -938,7 +938,7 @@ void MachObjectWriter::writeMachOHeader(MCAssembler &Asm) { unsigned Flags = Sec.getTypeAndAttributes(); if (Sec.hasInstructions()) Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS; - if (!cast(Sec).isVirtualSection() && + if (!cast(Sec).isBssSection() && !isUInt<32>(SectionStart)) { getContext().reportError( SMLoc(), "cannot encode offset of section; object file too large"); diff --git a/llvm/lib/ObjCopy/MachO/MachOObject.h b/llvm/lib/ObjCopy/MachO/MachOObject.h index 8f9444f5fb025..86c6b120fa6c3 100644 --- a/llvm/lib/ObjCopy/MachO/MachOObject.h +++ b/llvm/lib/ObjCopy/MachO/MachOObject.h @@ -64,14 +64,14 @@ struct Section { return static_cast(Flags & MachO::SECTION_TYPE); } - bool isVirtualSection() const { + bool isBssSection() const { return (getType() == MachO::S_ZEROFILL || getType() == MachO::S_GB_ZEROFILL || getType() == MachO::S_THREAD_LOCAL_ZEROFILL); } bool hasValidOffset() const { - return !(isVirtualSection() || OriginalOffset == 0); + return !(isBssSection() || OriginalOffset == 0); } }; diff --git a/llvm/lib/ObjCopy/MachO/MachOWriter.cpp b/llvm/lib/ObjCopy/MachO/MachOWriter.cpp index 7c24d1277dc8d..89c1df8699298 100644 --- a/llvm/lib/ObjCopy/MachO/MachOWriter.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOWriter.cpp @@ -112,7 +112,7 @@ size_t MachOWriter::totalSize() const { for (const std::unique_ptr
&S : LC.Sections) { if (!S->hasValidOffset()) { assert((S->Offset == 0) && "Skipped section's offset must be zero"); - assert((S->isVirtualSection() || S->Size == 0) && + assert((S->isBssSection() || S->Size == 0) && "Non-zero-fill sections with zero offset must have zero size"); continue; } @@ -240,7 +240,7 @@ void MachOWriter::writeSections() { for (const std::unique_ptr
&Sec : LC.Sections) { if (!Sec->hasValidOffset()) { assert((Sec->Offset == 0) && "Skipped section's offset must be zero"); - assert((Sec->isVirtualSection() || Sec->Size == 0) && + assert((Sec->isBssSection() || Sec->Size == 0) && "Non-zero-fill sections with zero offset must have zero size"); continue; } From cb6dd00ab3d461d90be5669e6e47edeb7eca7b4f Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 20 Jul 2025 11:02:25 -0700 Subject: [PATCH 18/39] MC: Replace getOrCreateDataFragment with getCurrentFragment Add an assert to ensure `CurFrag` is either null or an `FT_Data` fragment. Follow-up to 39c8cfb70d203439e3296dfdfe3d41f1cb2ec551. Extracted from #149721 --- llvm/include/llvm/MC/MCObjectStreamer.h | 3 --- llvm/include/llvm/MC/MCStreamer.h | 4 ++++ llvm/lib/MC/MCObjectStreamer.cpp | 18 +++++++++--------- llvm/lib/MC/MCWin64EH.cpp | 2 +- llvm/lib/MC/MCWinCOFFStreamer.cpp | 10 +++++----- llvm/lib/MC/MCXCOFFStreamer.cpp | 2 +- .../Target/ARM/MCTargetDesc/ARMELFStreamer.cpp | 6 +++--- .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 12 ++++++------ 8 files changed, 29 insertions(+), 28 deletions(-) diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 633334ee8a33f..429a1bb3321f6 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -72,9 +72,6 @@ class MCObjectStreamer : public MCStreamer { MCSymbol *emitCFILabel() override; void emitCFISections(bool EH, bool Debug) override; - // TODO: Change callers to use getCurrentFragment instead. - MCFragment *getOrCreateDataFragment() { return getCurrentFragment(); } - protected: bool changeSectionImpl(MCSection *Section, uint32_t Subsection); diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index b60082f4e8e17..c57a646c89247 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -437,8 +437,12 @@ class LLVM_ABI MCStreamer { } MCFragment *getCurrentFragment() const { + // Ensure consistency with the section stack. assert(!getCurrentSection().first || CurFrag->getParent() == getCurrentSection().first); + // Ensure we eagerly allocate an empty fragment after adding fragment with a + // variable-size tail. + assert(!CurFrag || CurFrag->getKind() == MCFragment::FT_Data); return CurFrag; } /// Save the current and previous section on the section stack. diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 83e447abb7e06..4c99010700fc7 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -119,7 +119,7 @@ void MCObjectStreamer::emitCFISections(bool EH, bool Debug) { void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) { MCStreamer::emitValueImpl(Value, Size, Loc); - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); MCDwarfLineEntry::make(this, getCurrentSectionOnly()); @@ -168,7 +168,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { // If there is a current fragment, mark the symbol as pointing into it. // Otherwise queue the label and set its fragment pointer when we emit the // next fragment. - MCFragment *F = getOrCreateDataFragment(); + MCFragment *F = getCurrentFragment(); Symbol->setFragment(F); Symbol->setOffset(F->getContents().size()); @@ -202,7 +202,7 @@ void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) { emitULEB128IntValue(IntValue); return; } - auto *F = getOrCreateDataFragment(); + auto *F = getCurrentFragment(); F->makeLEB(false, Value); newFragment(); } @@ -213,7 +213,7 @@ void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) { emitSLEB128IntValue(IntValue); return; } - auto *F = getOrCreateDataFragment(); + auto *F = getCurrentFragment(); F->makeLEB(true, Value); newFragment(); } @@ -312,7 +312,7 @@ void MCObjectStreamer::emitInstruction(const MCInst &Inst, void MCObjectStreamer::emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) { - MCFragment *F = getOrCreateDataFragment(); + MCFragment *F = getCurrentFragment(); // Append the instruction to the data fragment. size_t FixupStartIndex = F->getFixups().size(); @@ -344,7 +344,7 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst, void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &STI) { - auto *F = getOrCreateDataFragment(); + auto *F = getCurrentFragment(); SmallVector Data; SmallVector Fixups; getAssembler().getEmitter().encodeInstruction(Inst, Data, Fixups, STI); @@ -417,7 +417,7 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, return; } - auto *F = getOrCreateDataFragment(); + auto *F = getCurrentFragment(); F->Kind = MCFragment::FT_Dwarf; F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, SMLoc())); F->setDwarfLineDelta(LineDelta); @@ -449,7 +449,7 @@ void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section, void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label, SMLoc Loc) { - auto *F = getOrCreateDataFragment(); + auto *F = getCurrentFragment(); F->Kind = MCFragment::FT_DwarfFrame; F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, Loc)); newFragment(); @@ -511,7 +511,7 @@ void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) { void MCObjectStreamer::emitBytes(StringRef Data) { MCDwarfLineEntry::make(this, getCurrentSectionOnly()); - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); DF->appendContents(ArrayRef(Data.data(), Data.size())); } diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp index e8b26bf291ee4..a1c049aaed9cb 100644 --- a/llvm/lib/MC/MCWin64EH.cpp +++ b/llvm/lib/MC/MCWin64EH.cpp @@ -318,7 +318,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { // Emit the epilog instructions. if (EnableUnwindV2) { - MCFragment *DF = OS->getOrCreateDataFragment(); + MCFragment *DF = OS->getCurrentFragment(); bool IsLast = true; for (const auto &Epilog : llvm::reverse(info->EpilogMap)) { diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp index 3398775df3f91..370280eb87cfd 100644 --- a/llvm/lib/MC/MCWinCOFFStreamer.cpp +++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp @@ -278,7 +278,7 @@ void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) { void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) { visitUsedSymbol(*Symbol); - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2); DF->addFixup(Fixup); @@ -288,7 +288,7 @@ void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) { void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol, uint64_t Offset) { visitUsedSymbol(*Symbol); - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); // Create Symbol A for the relocation relative reference. const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); // Add the constant offset, if given. @@ -306,7 +306,7 @@ void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol, void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol, int64_t Offset) { visitUsedSymbol(*Symbol); - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); // Create Symbol A for the relocation relative reference. const MCExpr *MCE = MCSymbolRefExpr::create( Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext()); @@ -324,7 +324,7 @@ void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol, void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) { visitUsedSymbol(*Symbol); - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); // Create Symbol for section number. const MCExpr *MCE = MCCOFFSectionNumberTargetExpr::create( *Symbol, this->getWriter(), getContext()); @@ -338,7 +338,7 @@ void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) { void MCWinCOFFStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) { visitUsedSymbol(*Symbol); - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); // Create Symbol for section offset. const MCExpr *MCE = MCCOFFSectionOffsetTargetExpr::create(*Symbol, getContext()); diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp index 4d4529653aba9..63381b4f81859 100644 --- a/llvm/lib/MC/MCXCOFFStreamer.cpp +++ b/llvm/lib/MC/MCXCOFFStreamer.cpp @@ -89,7 +89,7 @@ void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility( void MCXCOFFStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) { // Add a Fixup here to later record a relocation of type R_REF to prevent the // ref symbol from being garbage collected (by the binder). - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); std::optional MaybeKind = getAssembler().getBackend().getFixupKind("R_REF"); diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index eaba6fe5bfcb7..a7a9911de2d04 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -593,7 +593,7 @@ class ARMELFStreamer : public MCELFStreamer { getContext().reportError(Loc, "relocated expression must be 32-bit"); return; } - getOrCreateDataFragment(); + getCurrentFragment(); } emitDataMappingSymbol(); @@ -1207,7 +1207,7 @@ inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) { } void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) { - MCFragment *Frag = getOrCreateDataFragment(); + MCFragment *Frag = getCurrentFragment(); Frag->addFixup(MCFixup::create(Frag->getContents().size(), Expr, Kind)); } @@ -1295,7 +1295,7 @@ void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) { MCSymbolRefExpr::create(PersonalitySym, ARM::S_ARM_NONE, getContext()); visitUsedExpr(*PersonalityRef); - MCFragment *DF = getOrCreateDataFragment(); + MCFragment *DF = getCurrentFragment(); DF->addFixup( MCFixup::create(DF->getContents().size(), PersonalityRef, FK_Data_4)); } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index b89d6890903dd..5c7f34b870847 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -1033,42 +1033,42 @@ MCELFStreamer &MipsTargetELFStreamer::getStreamer() { } void MipsTargetELFStreamer::emitGPRel32Value(const MCExpr *Value) { - MCFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getCurrentFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_GPREL32)); DF->appendContents(4, 0); } void MipsTargetELFStreamer::emitGPRel64Value(const MCExpr *Value) { - MCFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getCurrentFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_GPREL32)); DF->appendContents(8, 0); } void MipsTargetELFStreamer::emitDTPRel32Value(const MCExpr *Value) { - MCFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getCurrentFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_DTPREL32)); DF->appendContents(4, 0); } void MipsTargetELFStreamer::emitDTPRel64Value(const MCExpr *Value) { - MCFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getCurrentFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_DTPREL64)); DF->appendContents(8, 0); } void MipsTargetELFStreamer::emitTPRel32Value(const MCExpr *Value) { - MCFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getCurrentFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_TPREL32)); DF->appendContents(4, 0); } void MipsTargetELFStreamer::emitTPRel64Value(const MCExpr *Value) { - MCFragment *DF = getStreamer().getOrCreateDataFragment(); + MCFragment *DF = getStreamer().getCurrentFragment(); DF->addFixup(MCFixup::create(DF->getContents().size(), Value, Mips::fixup_Mips_TPREL64)); DF->appendContents(8, 0); From c7aab2565336ea0fb6e4a73726c9ec64a78e6450 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 20 Jul 2025 11:11:21 -0700 Subject: [PATCH 19/39] MC: Fix fragment-in-BSS check * Handle non-zero fill values for `.fill` and `.org` directives. * Restore the fragment type check (5ee34ff1e5cc952116f0da943ddaeb1a71db2940 removed a reachable `llvm_unreachable`) to detect unintended API usage. Remove virtual functions `getVirtualSectionKind` (added in https://reviews.llvm.org/D78138) as they are unnecessary in diagnostics. The a.out object file format has the BSS concept, which has been inherited by COFF, XCOFF, Mach-O, and ELF object file formats. Pull Request: https://github.com/llvm/llvm-project/pull/149721 --- llvm/include/llvm/MC/MCSection.h | 8 +++--- llvm/include/llvm/MC/MCSectionCOFF.h | 1 - llvm/include/llvm/MC/MCSectionELF.h | 1 - llvm/lib/MC/MCAssembler.cpp | 32 ++++++++++++++++++++---- llvm/lib/MC/MCParser/AsmParser.cpp | 5 ++-- llvm/lib/MC/MCSection.cpp | 8 +++--- llvm/lib/MC/MCSectionCOFF.cpp | 4 --- llvm/lib/MC/MCSectionELF.cpp | 2 -- llvm/test/MC/COFF/bss-text.s | 4 +-- llvm/test/MC/ELF/nobits-non-zero-value.s | 31 +++++++++++++++++------ 10 files changed, 61 insertions(+), 35 deletions(-) diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 22786bde75773..ce295728c4efd 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -113,7 +113,7 @@ class LLVM_ABI MCSection { StringRef Name; SectionVariant Variant; - MCSection(SectionVariant V, StringRef Name, bool IsText, bool IsVirtual, + MCSection(SectionVariant V, StringRef Name, bool IsText, bool IsBss, MCSymbol *Begin); // Protected non-virtual dtor prevents destroy through a base class pointer. ~MCSection() {} @@ -176,11 +176,9 @@ class LLVM_ABI MCSection { /// instead of 0s. virtual bool useCodeAlign() const = 0; - /// Return true if this is a BSS section (e.g., ELF .bss or .tbss) that does - /// not store content and is typically initialized to zeroes by the runtime. + /// Check whether this section is "virtual", that is has no actual object + /// file contents. bool isBssSection() const { return IsBss; } - - virtual StringRef getVirtualSectionKind() const; }; // Represents a contiguous piece of code or data within a section. Its size is diff --git a/llvm/include/llvm/MC/MCSectionCOFF.h b/llvm/include/llvm/MC/MCSectionCOFF.h index 4472a128caa6b..f979413a3791e 100644 --- a/llvm/include/llvm/MC/MCSectionCOFF.h +++ b/llvm/include/llvm/MC/MCSectionCOFF.h @@ -82,7 +82,6 @@ class MCSectionCOFF final : public MCSection { raw_ostream &OS, uint32_t Subsection) const override; bool useCodeAlign() const override; - StringRef getVirtualSectionKind() const override; unsigned getOrAssignWinCFISectionID(unsigned *NextID) const { if (WinCFISectionID == ~0U) diff --git a/llvm/include/llvm/MC/MCSectionELF.h b/llvm/include/llvm/MC/MCSectionELF.h index f09d30591a3cf..a01f95f44c954 100644 --- a/llvm/include/llvm/MC/MCSectionELF.h +++ b/llvm/include/llvm/MC/MCSectionELF.h @@ -88,7 +88,6 @@ class MCSectionELF final : public MCSection { raw_ostream &OS, uint32_t Subsection) const override; bool useCodeAlign() const override; - StringRef getVirtualSectionKind() const override; bool isUnique() const { return UniqueID != NonUniqueID; } unsigned getUniqueID() const { return UniqueID; } diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 317ba8128cff1..26726c0902f5a 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -567,15 +567,37 @@ void MCAssembler::writeSectionData(raw_ostream &OS, // not tracked for efficiency. auto Fn = [](char c) { return c != 0; }; for (const MCFragment &F : *Sec) { - if (any_of(F.getContents(), Fn) || any_of(F.getVarContents(), Fn)) { - reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + - Sec->getName() + + bool HasNonZero = false; + switch (F.getKind()) { + default: + reportFatalInternalError("BSS section '" + Sec->getName() + + "' contains invalid fragment"); + break; + case MCFragment::FT_Data: + case MCFragment::FT_Relaxable: + HasNonZero = + any_of(F.getContents(), Fn) || any_of(F.getVarContents(), Fn); + break; + case MCFragment::FT_Align: + // Disallowed for API usage. AsmParser changes non-zero fill values to + // 0. + assert(F.getAlignFill() == 0 && "Invalid align in virtual section!"); + break; + case MCFragment::FT_Fill: + HasNonZero = cast(F).getValue() != 0; + break; + case MCFragment::FT_Org: + HasNonZero = cast(F).getValue() != 0; + break; + } + if (HasNonZero) { + reportError(SMLoc(), "BSS section '" + Sec->getName() + "' cannot have non-zero bytes"); break; } if (F.getFixups().size() || F.getVarFixups().size()) { - reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + - Sec->getName() + "' cannot have fixups"); + reportError(SMLoc(), + "BSS section '" + Sec->getName() + "' cannot have fixups"); break; } } diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 4c55e97f0c1fc..d0b6ea4cfd562 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -3406,9 +3406,8 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, uint8_t ValueSize) { if (HasFillExpr && FillExpr != 0 && Section->isBssSection()) { ReturnVal |= - Warning(FillExprLoc, "ignoring non-zero fill value in " + - Section->getVirtualSectionKind() + - " section '" + Section->getName() + "'"); + Warning(FillExprLoc, "ignoring non-zero fill value in BSS section '" + + Section->getName() + "'"); FillExpr = 0; } diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index fd1d072cf4152..1b5a7b337c207 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -18,10 +18,10 @@ using namespace llvm; -MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText, - bool IsVirtual, MCSymbol *Begin) +MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText, bool IsBss, + MCSymbol *Begin) : Begin(Begin), HasInstructions(false), IsRegistered(false), IsText(IsText), - IsBss(IsVirtual), LinkerRelaxable(false), Name(Name), Variant(V) { + IsBss(IsBss), LinkerRelaxable(false), Name(Name), Variant(V) { // The initial subsection number is 0. Create a fragment list. CurFragList = &Subsections.emplace_back(0u, FragList{}).second; } @@ -34,8 +34,6 @@ MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) { bool MCSection::hasEnded() const { return End && End->isInSection(); } -StringRef MCSection::getVirtualSectionKind() const { return "virtual"; } - #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MCSection::dump( DenseMap> *FragToSyms) diff --git a/llvm/lib/MC/MCSectionCOFF.cpp b/llvm/lib/MC/MCSectionCOFF.cpp index 94e29ce27d881..5bf14735eda9b 100644 --- a/llvm/lib/MC/MCSectionCOFF.cpp +++ b/llvm/lib/MC/MCSectionCOFF.cpp @@ -115,7 +115,3 @@ void MCSectionCOFF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, } bool MCSectionCOFF::useCodeAlign() const { return isText(); } - -StringRef MCSectionCOFF::getVirtualSectionKind() const { - return "IMAGE_SCN_CNT_UNINITIALIZED_DATA"; -} diff --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp index 299fe40706e3a..ef33f9c314579 100644 --- a/llvm/lib/MC/MCSectionELF.cpp +++ b/llvm/lib/MC/MCSectionELF.cpp @@ -215,5 +215,3 @@ void MCSectionELF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, bool MCSectionELF::useCodeAlign() const { return getFlags() & ELF::SHF_EXECINSTR; } - -StringRef MCSectionELF::getVirtualSectionKind() const { return "SHT_NOBITS"; } diff --git a/llvm/test/MC/COFF/bss-text.s b/llvm/test/MC/COFF/bss-text.s index 439bd789dff2c..cedbb2f032236 100644 --- a/llvm/test/MC/COFF/bss-text.s +++ b/llvm/test/MC/COFF/bss-text.s @@ -4,11 +4,11 @@ # RUN: llvm-mc -triple=x86_64-pc-win32 %s .bss -# CHECK: :0: error: IMAGE_SCN_CNT_UNINITIALIZED_DATA section '.bss' cannot have non-zero bytes +# CHECK: :0: error: BSS section '.bss' cannot have non-zero bytes addb %bl,(%rax) .section uninitialized,"b" -# CHECK: :0: error: IMAGE_SCN_CNT_UNINITIALIZED_DATA section 'uninitialized' cannot have non-zero bytes +# CHECK: :0: error: BSS section 'uninitialized' cannot have non-zero bytes jmp foo .section bss0,"b" diff --git a/llvm/test/MC/ELF/nobits-non-zero-value.s b/llvm/test/MC/ELF/nobits-non-zero-value.s index e9516aa3e835a..ea95ec97ac8d2 100644 --- a/llvm/test/MC/ELF/nobits-non-zero-value.s +++ b/llvm/test/MC/ELF/nobits-non-zero-value.s @@ -9,20 +9,37 @@ .bss addb %al,(%rax) -# CHECK: {{.*}}.s:[[#@LINE+1]]:11: warning: ignoring non-zero fill value in SHT_NOBITS section '.bss' +# CHECK: {{.*}}.s:[[#@LINE+1]]:11: warning: ignoring non-zero fill value in BSS section '.bss' .align 4, 42 -.align 4, 0 - .long 1 .section .bss0,"aw",%nobits addb %al,(%rax) -.section .bss1,"aw",%nobits +.section data_fixup,"aw",%nobits .quad foo +.section fill,"aw",%nobits +.fill b-a,1,1 + +.section org,"aw",%nobits +.org 1,1 + +.section ok,"aw",%nobits +.org 1 +.fill 1 +.fill b-a,1,0 +.align 4, 0 +.long 0 + +.text +a: nop +b: + ## Location is not tracked for efficiency. -# CHECK: :0: error: SHT_NOBITS section '.tbss' cannot have non-zero bytes -# CHECK: :0: error: SHT_NOBITS section '.bss' cannot have non-zero bytes -# CHECK: :0: error: SHT_NOBITS section '.bss1' cannot have fixups +# CHECK: :0: error: BSS section '.tbss' cannot have non-zero bytes +# CHECK: :0: error: BSS section '.bss' cannot have non-zero bytes +# CHECK: :0: error: BSS section 'data_fixup' cannot have fixups +# CHECK: :0: error: BSS section 'fill' cannot have non-zero bytes +# CHECK: :0: error: BSS section 'org' cannot have non-zero bytes From 4e420df887dd61c8a7e7bcf7d2923bcd4669bd1e Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 18:25:38 -0700 Subject: [PATCH 20/39] WIP fix MCCAS from MaskRay MC changes, remove obsolete fragment types from MCCASObjectV1.def --- llvm/include/llvm/MCCAS/MCCASObjectV1.def | 7 ------- 1 file changed, 7 deletions(-) diff --git a/llvm/include/llvm/MCCAS/MCCASObjectV1.def b/llvm/include/llvm/MCCAS/MCCASObjectV1.def index df630e851dd35..076ed1e2e409e 100644 --- a/llvm/include/llvm/MCCAS/MCCASObjectV1.def +++ b/llvm/include/llvm/MCCAS/MCCASObjectV1.def @@ -72,23 +72,16 @@ CASV1_SIMPLE_GROUP_REF(DIEDedupeTopLevelRef, mc:debug_DIE_Dedupe_top_level) #ifdef MCFRAGMENT_NODE_REF #ifndef MCFRAGMENT_ENCODED_FRAGMENT_ONLY -MCFRAGMENT_NODE_REF(MCAlignFragment, FT_Align, mc:align) MCFRAGMENT_NODE_REF(MCBoundaryAlignFragment, FT_BoundaryAlign, mc:boundary_align) MCFRAGMENT_NODE_REF(MCCVInlineLineTableFragment, FT_CVInlineLines, mc:cv_inline_lines) MCFRAGMENT_NODE_REF(MCFillFragment, FT_Fill, mc:fill) -MCFRAGMENT_NODE_REF(MCLEBFragment, FT_LEB, mc:leb) MCFRAGMENT_NODE_REF(MCNopsFragment, FT_Nops, mc:nops) MCFRAGMENT_NODE_REF(MCOrgFragment, FT_Org, mc:org) MCFRAGMENT_NODE_REF(MCSymbolIdFragment, FT_SymbolId, mc:symbol_id) #endif /* MCFRAGMENT_ENCODED_FRAGMENT_ONLY */ #undef MCFRAGMENT_ENCODED_FRAGMENT_ONLY -MCFRAGMENT_NODE_REF(MCDataFragment, FT_Data, mc:data) -MCFRAGMENT_NODE_REF(MCRelaxableFragment, FT_Relaxable, mc:relaxable) -MCFRAGMENT_NODE_REF(MCDwarfLineAddrFragment, FT_Dwarf, mc:dwarf) -MCFRAGMENT_NODE_REF(MCDwarfCallFrameFragment, FT_DwarfFrame, mc:dwarf_frame) MCFRAGMENT_NODE_REF(MCCVDefRangeFragment, FT_CVDefRange, mc:cv_def_range) -MCFRAGMENT_NODE_REF(MCPseudoProbeAddrFragment, FT_PseudoProbe, mc:presudo_pro) #undef MCFRAGMENT_NODE_REF #endif /* MCFRAGMENT_NODE_REF */ From 84bc22edff78d6c519b0b4a8ab4641bac331aacc Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 18:52:19 -0700 Subject: [PATCH 21/39] WIP MCCAS MaskRay Fix, fix MCRelaxableFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 0d4861d4a5f94..41f1087df4e45 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2127,9 +2127,6 @@ MCCASBuilder::mergeMCFragmentContents(const MCSection *Section, for (const MCFragment &Fragment : *Section) { if (const auto *DataFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, DataFragment->getContents()); - else if (const auto *RelaxableFragment = - dyn_cast(&Fragment)) - llvm::append_range(mergedData, RelaxableFragment->getContents()); else if (const auto *DwarfLineAddrFrag = dyn_cast(&Fragment)) if (IsDebugLineSection) @@ -2157,7 +2154,9 @@ MCCASBuilder::mergeMCFragmentContents(const MCSection *Section, raw_svector_ostream OS(mergedData); if (auto E = writeAlignFragment(*this, *AlignFragment, OS, FragmentSize)) return std::move(E); - } else + } else if (Fragment.getFixedSize() != 0) + llvm::append_range(mergedData, Fragment.getContents()); + else // All other fragment types can be considered empty, see // getFragmentContents() for all fragments that have contents. continue; From 637e8f821d1b713b11668e938fca0de8f254f3ef Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 18:53:53 -0700 Subject: [PATCH 22/39] WIP MCCAS MaskRay Fix, fix MCDwarfCallFrameFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 41f1087df4e45..3eaff67034e92 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2135,9 +2135,6 @@ MCCASBuilder::mergeMCFragmentContents(const MCSection *Section, return createStringError( inconvertibleErrorCode(), "Invalid MCDwarfLineAddrFragment in a non debug line section"); - else if (const auto *DwarfCallFrameFragment = - dyn_cast(&Fragment)) - llvm::append_range(mergedData, DwarfCallFrameFragment->getContents()); else if (const auto *CVDefRangeFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, CVDefRangeFragment->getContents()); From 303cbbc5bc45eb6bb2329292cc271b0e4d7cb2f3 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 18:59:52 -0700 Subject: [PATCH 23/39] WIP MCCAS MaskRay Fix, fix MCPseudoProbeFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 3eaff67034e92..8586d843bffae 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2138,9 +2138,6 @@ MCCASBuilder::mergeMCFragmentContents(const MCSection *Section, else if (const auto *CVDefRangeFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, CVDefRangeFragment->getContents()); - else if (const auto *PseudoProbeAddrFragment = - dyn_cast(&Fragment)) - llvm::append_range(mergedData, PseudoProbeAddrFragment->getContents()); else if (const auto *LEBFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, LEBFragment->getContents()); else if (const auto *CVInlineLineTableFragment = From fa104f2d813aa8cd58dac0efe906ea23080f28f3 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 19:02:20 -0700 Subject: [PATCH 24/39] WIP MCCAS MaskRay Fix, fix MCLEBFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 8586d843bffae..222a8cee6dee9 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2138,8 +2138,6 @@ MCCASBuilder::mergeMCFragmentContents(const MCSection *Section, else if (const auto *CVDefRangeFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, CVDefRangeFragment->getContents()); - else if (const auto *LEBFragment = dyn_cast(&Fragment)) - llvm::append_range(mergedData, LEBFragment->getContents()); else if (const auto *CVInlineLineTableFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, CVInlineLineTableFragment->getContents()); From e41c5b25890e93b4c4349b315807c1a12058c0a2 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 19:43:31 -0700 Subject: [PATCH 25/39] WIP MCCAS MaskRay Fix, fix MCDwarfLineAddrFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 222a8cee6dee9..05fe5601b5645 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2127,14 +2127,13 @@ MCCASBuilder::mergeMCFragmentContents(const MCSection *Section, for (const MCFragment &Fragment : *Section) { if (const auto *DataFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, DataFragment->getContents()); - else if (const auto *DwarfLineAddrFrag = - dyn_cast(&Fragment)) + else if (Fragment.getKind() == MCFragment::FT_Dwarf) if (IsDebugLineSection) - llvm::append_range(mergedData, DwarfLineAddrFrag->getContents()); + llvm::append_range(mergedData, Fragment.getContents()); else return createStringError( inconvertibleErrorCode(), - "Invalid MCDwarfLineAddrFragment in a non debug line section"); + "Invalid MCFragment::FT_Dwarf type in a non debug line section"); else if (const auto *CVDefRangeFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, CVDefRangeFragment->getContents()); From 8d4cdfc0222fa9dde9864d4f9b808dc1713ba1b3 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 20:09:37 -0700 Subject: [PATCH 26/39] WIP MCCAS MaskRay Fix, do some work for MCAlignFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 05fe5601b5645..1c4db3f2630e4 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -1919,11 +1919,10 @@ Error MCDataFragmentMerger::tryMerge(const MCFragment &F, unsigned Size, return Error::success(); } -static Error writeAlignFragment(MCCASBuilder &Builder, - const MCAlignFragment &AF, raw_ostream &OS, - unsigned FragmentSize) { - uint64_t Count = FragmentSize / AF.getFillLen(); - if (AF.hasEmitNops()) { +static Error writeAlignFragment(MCCASBuilder &Builder, const MCFragment &AF, + raw_ostream &OS, unsigned FragmentSize) { + uint64_t Count = FragmentSize / AF.getAlignFillLen(); + if (AF.hasAlignEmitNops()) { if (!Builder.Asm.getBackend().writeNopData(OS, Count, AF.getSubtargetInfo())) return createStringError(inconvertibleErrorCode(), @@ -1934,20 +1933,20 @@ static Error writeAlignFragment(MCCASBuilder &Builder, auto Endian = Builder.ObjectWriter.Target.isLittleEndian() ? endianness::little : endianness::big; for (uint64_t I = 0; I != Count; ++I) { - switch (AF.getFillLen()) { + switch (AF.getAlignFillLen()) { default: llvm_unreachable("Invalid size!"); case 1: - OS << char(AF.getFill()); + OS << char(AF.getAlignFill()); break; case 2: - support::endian::write(OS, AF.getFill(), Endian); + support::endian::write(OS, AF.getAlignFill(), Endian); break; case 4: - support::endian::write(OS, AF.getFill(), Endian); + support::endian::write(OS, AF.getAlignFill(), Endian); break; case 8: - support::endian::write(OS, AF.getFill(), Endian); + support::endian::write(OS, AF.getAlignFill(), Endian); break; } } @@ -2140,10 +2139,10 @@ MCCASBuilder::mergeMCFragmentContents(const MCSection *Section, else if (const auto *CVInlineLineTableFragment = dyn_cast(&Fragment)) llvm::append_range(mergedData, CVInlineLineTableFragment->getContents()); - else if (const auto *AlignFragment = dyn_cast(&Fragment)) { + else if (Fragment.getKind() == MCFragment::FT_Align) { auto FragmentSize = Asm.computeFragmentSize(Fragment); raw_svector_ostream OS(mergedData); - if (auto E = writeAlignFragment(*this, *AlignFragment, OS, FragmentSize)) + if (auto E = writeAlignFragment(*this, Fragment, OS, FragmentSize)) return std::move(E); } else if (Fragment.getFixedSize() != 0) llvm::append_range(mergedData, Fragment.getContents()); From f1102ae04f7b7aec2e6f954659eaf6470ff10873 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 20:16:32 -0700 Subject: [PATCH 27/39] WIP MCCAS MaskRay Fix, Fix some stuff for MCDataFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 1c4db3f2630e4..6becd8e7eab6a 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2124,9 +2124,7 @@ MCCASBuilder::mergeMCFragmentContents(const MCSection *Section, bool IsDebugLineSection) { SmallVector mergedData; for (const MCFragment &Fragment : *Section) { - if (const auto *DataFragment = dyn_cast(&Fragment)) - llvm::append_range(mergedData, DataFragment->getContents()); - else if (Fragment.getKind() == MCFragment::FT_Dwarf) + if (Fragment.getKind() == MCFragment::FT_Dwarf) if (IsDebugLineSection) llvm::append_range(mergedData, Fragment.getContents()); else From c404734e706b1bf7d7d12bb441c0902c189d78ce Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 20:19:07 -0700 Subject: [PATCH 28/39] WIP MCCAS MaskRay Fix, Fix some more stuff for MCDataFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 6becd8e7eab6a..b4a272aaa5d54 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2595,7 +2595,7 @@ Expected> MCCASBuilder::createDebugStringRefs() { SmallVector DebugStringRefs; ArrayRef DebugStrData = - cast(*DwarfSections.Str->begin()).getContents(); + cast(*DwarfSections.Str->begin()).getContents(); StringRef S(DebugStrData.data(), DebugStrData.size()); if (auto E = createStringSection(S, [&](StringRef S) -> Error { auto Sym = DebugStrRef::create(*this, S); From f656afc94dab68125e8d2629c055633a96fc7a8e Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 20:23:05 -0700 Subject: [PATCH 29/39] WIP MCCAS MaskRayFix, Replace isVirtualSection with isBssSection --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index b4a272aaa5d54..2a06f50eddbce 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2947,7 +2947,7 @@ Error MCCASBuilder::buildFragments() { startGroup(); for (const MCSection &Sec : Asm) { - if (Sec.isVirtualSection()) + if (Sec.isBssSection()) continue; // Handle Debug Info sections separately. From 90d2cc103b2345465ccb9dad3bf97d5e69b8c66d Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 20:24:17 -0700 Subject: [PATCH 30/39] WIP MCCAS MaskRay Fix, Change isa to F.getKind() == MCFragment::FT_Align --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 2a06f50eddbce..b2f868ecaffdd 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -1887,7 +1887,7 @@ Error MCDataFragmentMerger::tryMerge(const MCFragment &F, unsigned Size, bool Oversized = CurrentSize + Size > MCDataMergeThreshold; // TODO: Try merge align fragment? bool IsMergeableFragment = - isa(F) || isa(F); + isa(F) || F.getKind() == MCFragment::FT_Align; // If not the same atom, flush merge candidate and return false. if (!IsSameAtom || !IsMergeableFragment || Oversized) { if (auto E = emitMergedFragments()) From 04ed4ab83ffdef856678a7d1151e6bd933b1e080 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 20:29:53 -0700 Subject: [PATCH 31/39] WIP MCCAS MaskRay Fix, some more work for MCAlignFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index b2f868ecaffdd..2a0c5d8502333 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -1978,9 +1978,8 @@ Error MCDataFragmentMerger::emitMergedFragments() { #define MCFRAGMENT_ENCODED_FRAGMENT_ONLY #include "llvm/MCCAS/MCCASObjectV1.def" case MCFragment::FT_Align: { - const MCAlignFragment *AF = cast(Candidate.first); - if (auto E = - writeAlignFragment(Builder, *AF, FragmentOS, Candidate.second)) + if (auto E = writeAlignFragment(Builder, *Candidate.first, FragmentOS, + Candidate.second)) return E; break; } From 4f997d56fb37da34973971c7c6e397b2ea82a40c Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 20:37:59 -0700 Subject: [PATCH 32/39] MCCAS MaskRay Fix, a little more MCLEBFragment fix --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 2a0c5d8502333..f0e6168f30110 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2861,8 +2861,7 @@ static ArrayRef getFragmentContents(const MCFragment &Fragment) { return SF.getContents(); } case MCFragment::FT_LEB: { - const MCLEBFragment &SF = cast(Fragment); - return SF.getContents(); + return Fragment.getContents(); } default: return ArrayRef(); From 6ee9a0615166b0308b35d32b476e1abc92f9f88c Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 21:30:45 -0700 Subject: [PATCH 33/39] WIP MCCAS MaskRay Fix, fixed bug with no more classof function in MCEncodedFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index f0e6168f30110..e62aa66f2d871 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -1557,7 +1557,8 @@ MCAlignFragmentRef::create(MCCASBuilder &MB, const MCAlignFragment &F, } Expected MCAlignFragmentRef::materialize(MCCASReader &Reader, - raw_ostream *Stream) const { + raw_ostream *Stream) const + { uint64_t Count; auto Remaining = getData(); auto Endian = Reader.getEndian(); @@ -1887,7 +1888,7 @@ Error MCDataFragmentMerger::tryMerge(const MCFragment &F, unsigned Size, bool Oversized = CurrentSize + Size > MCDataMergeThreshold; // TODO: Try merge align fragment? bool IsMergeableFragment = - isa(F) || F.getKind() == MCFragment::FT_Align; + F.isEncoded() || F.getKind() == MCFragment::FT_Align; // If not the same atom, flush merge candidate and return false. if (!IsSameAtom || !IsMergeableFragment || Oversized) { if (auto E = emitMergedFragments()) From 36becd86d27634b5dcfde104a98e4a67f6a80cd0 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Thu, 24 Jul 2025 23:52:40 -0700 Subject: [PATCH 34/39] WIP fix MCCAS, builds but round trip verification error due to FragType not staying the same after materialization, does it not get saved? --- llvm/include/llvm/MCCAS/MCCASObjectV1.def | 1 + llvm/include/llvm/MCCAS/MCCASObjectV1.h | 57 ++++++++++ llvm/lib/MCCAS/MCCASObjectV1.cpp | 122 ++++++++++++++++++---- 3 files changed, 160 insertions(+), 20 deletions(-) diff --git a/llvm/include/llvm/MCCAS/MCCASObjectV1.def b/llvm/include/llvm/MCCAS/MCCASObjectV1.def index 076ed1e2e409e..5e7667ad8a713 100644 --- a/llvm/include/llvm/MCCAS/MCCASObjectV1.def +++ b/llvm/include/llvm/MCCAS/MCCASObjectV1.def @@ -85,3 +85,4 @@ MCFRAGMENT_NODE_REF(MCCVDefRangeFragment, FT_CVDefRange, mc:cv_def_range) #undef MCFRAGMENT_NODE_REF #endif /* MCFRAGMENT_NODE_REF */ + diff --git a/llvm/include/llvm/MCCAS/MCCASObjectV1.h b/llvm/include/llvm/MCCAS/MCCASObjectV1.h index 6cce778a8e803..fef193b38aeb8 100644 --- a/llvm/include/llvm/MCCAS/MCCASObjectV1.h +++ b/llvm/include/llvm/MCCAS/MCCASObjectV1.h @@ -418,6 +418,63 @@ class SpecificRef : public MCObjectProxy { }; #include "llvm/MCCAS/MCCASObjectV1.def" +class MCGenericFragmentRef : public SpecificRef { + using SpecificRefT = SpecificRef; + friend class SpecificRef; + +public: + MCGenericFragmentRef(SpecificRefT ST, MCFragment::FragmentType FragType) + : SpecificRef(ST), FragType(FragType) {} + MCFragment::FragmentType FragType; + static constexpr StringLiteral KindString = "mc:generic_fragment"; + static Expected create(MCCASBuilder &MB, + const MCFragment &Fragment, + unsigned FragmentSize, + ArrayRef FragmentContents); + static Expected get(Expected Ref, + MCFragment::FragmentType FragType) { + auto Specific = SpecificRefT::getSpecific(std::move(Ref)); + if (!Specific) + return Specific.takeError(); + return MCGenericFragmentRef(*Specific, FragType); + } + static Expected get(const MCSchema &Schema, + cas::ObjectRef ID, + MCFragment::FragmentType FragType) { + return get(Schema.get(ID), FragType); + } + static std::optional Cast(MCObjectProxy Ref) { + auto Specific = SpecificRefT::Cast(Ref); + if (!Specific) + return std::nullopt; + return MCGenericFragmentRef(*Specific); + } + Expected materialize(const MCFragment::FragmentType FragType, + MCCASReader &Reader, + raw_ostream *Stream) const; + + static Expected + createGenericAlignFragmentRef(MCCASBuilder &MB, const MCFragment &F, + unsigned FragmentSize, + ArrayRef FragmentContents); + + static Expected + createGenericLEBFragmentRef(MCCASBuilder &MB, const MCFragment &F, + unsigned FragmentSize, + ArrayRef FragmentContents); + + Expected + materializeGenericAlignFragmentRef(MCCASReader &Reader, + raw_ostream *Stream) const; + + Expected + materializeGenericLEBFragmentRef(MCCASReader &Reader, + raw_ostream *Stream) const; + +private: + explicit MCGenericFragmentRef(SpecificRefT Ref) : SpecificRefT(Ref) {} +}; + class PaddingRef : public SpecificRef { using SpecificRefT = SpecificRef; friend class SpecificRef; diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index e62aa66f2d871..9859af495f35c 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -48,6 +48,7 @@ constexpr StringLiteral PaddingRef::KindString; #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ constexpr StringLiteral MCFragmentName##Ref::KindString; #include "llvm/MCCAS/MCCASObjectV1.def" +constexpr StringLiteral MCGenericFragmentRef::KindString; constexpr StringLiteral DebugInfoSectionRef::KindString; void MCSchema::anchor() {} @@ -172,6 +173,7 @@ Error MCSchema::fillCache() { PaddingRef::KindString, MCAssemblerRef::KindString, DebugInfoSectionRef::KindString, + MCGenericFragmentRef::KindString, #define CASV1_SIMPLE_DATA_REF(RefName, IdentifierName) RefName::KindString, #define CASV1_SIMPLE_GROUP_REF(RefName, IdentifierName) RefName::KindString, #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ @@ -1531,16 +1533,16 @@ Expected AtomRef::materialize(MCCASReader &Reader, return Size; } -Expected -MCAlignFragmentRef::create(MCCASBuilder &MB, const MCAlignFragment &F, - unsigned FragmentSize, - ArrayRef FragmentContents) { +Expected +MCGenericFragmentRef::createGenericAlignFragmentRef( + MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, + ArrayRef FragmentContents) { Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); - uint64_t Count = FragmentSize / F.getFillLen(); - if (F.hasEmitNops()) { + uint64_t Count = FragmentSize / F.getAlignFillLen(); + if (F.hasAlignEmitNops()) { // Write 0 as size and use backend to emit nop. writeVBR8(0, B->Data); if (!MB.Asm.getBackend().writeNopData(MB.FragmentOS, Count, @@ -1548,17 +1550,16 @@ MCAlignFragmentRef::create(MCCASBuilder &MB, const MCAlignFragment &F, report_fatal_error("unable to write nop sequence of " + Twine(Count) + " bytes"); B->Data.append(MB.FragmentData); - return get(B->build()); + return get(B->build(), MCFragment::FT_Align); } writeVBR8(Count, B->Data); - writeVBR8(F.getFill(), B->Data); - writeVBR8(F.getFillLen(), B->Data); - return get(B->build()); + writeVBR8(F.getAlignFill(), B->Data); + writeVBR8(F.getAlignFillLen(), B->Data); + return get(B->build(), MCFragment::FT_Align); } -Expected MCAlignFragmentRef::materialize(MCCASReader &Reader, - raw_ostream *Stream) const - { +Expected MCGenericFragmentRef::materializeGenericAlignFragmentRef( + MCCASReader &Reader, raw_ostream *Stream) const { uint64_t Count; auto Remaining = getData(); auto Endian = Reader.getEndian(); @@ -1686,23 +1687,76 @@ Expected MCFillFragmentRef::materialize(MCCASReader &Reader, return Size; } -Expected -MCLEBFragmentRef::create(MCCASBuilder &MB, const MCLEBFragment &F, - unsigned FragmentSize, - ArrayRef FragmentContents) { +Expected +MCGenericFragmentRef::createGenericLEBFragmentRef( + MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, + ArrayRef FragmentContents) { Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); llvm::append_range(B->Data, F.getContents()); - return get(B->build()); + return get(B->build(), MCFragment::FT_LEB); } -Expected MCLEBFragmentRef::materialize(MCCASReader &Reader, - raw_ostream *Stream) const { +Expected MCGenericFragmentRef::materializeGenericLEBFragmentRef( + MCCASReader &Reader, raw_ostream *Stream) const { *Stream << getData(); return getData().size(); } +Expected +MCGenericFragmentRef::create(MCCASBuilder &MB, const MCFragment &Fragment, + unsigned int FragmentSize, + ArrayRef FragmentContents) { + auto FragType = Fragment.getKind(); + switch (FragType) { + case MCFragment::FT_Align: + return createGenericAlignFragmentRef(MB, Fragment, FragmentSize, + FragmentContents); + case MCFragment::FT_LEB: + return createGenericLEBFragmentRef(MB, Fragment, FragmentSize, + FragmentContents); + case MCFragment::FT_Relaxable: + case MCFragment::FT_Data: + case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: { + Expected B = Builder::startNode(MB.Schema, KindString); + if (!B) + return B.takeError(); + B->Data.append(MB.FragmentData); + B->Data.append(FragmentContents.begin(), FragmentContents.end()); + assert(((MB.FragmentData.empty() && Fragment.getContents().empty()) || + (MB.FragmentData.size() + Fragment.getContents().size() == + FragmentSize)) && + "Size should match"); + return get(B->build(), FragType); + } + default: + llvm_unreachable("Other Fragment Kinds should be handled elsewhere!"); + } +} + +Expected +MCGenericFragmentRef::materialize(const MCFragment::FragmentType FragType, + MCCASReader &Reader, + raw_ostream *Stream) const { + switch (FragType) { + case MCFragment::FT_Align: + return materializeGenericAlignFragmentRef(Reader, Stream); + case MCFragment::FT_LEB: + return materializeGenericLEBFragmentRef(Reader, Stream); + case MCFragment::FT_Relaxable: + case MCFragment::FT_Data: + case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: { + *Stream << getData(); + return getData().size(); + } + default: + llvm_unreachable("Other Fragment Kinds should be handled elsewhere!"); + } +} + Expected MCNopsFragmentRef::create(MCCASBuilder &MB, const MCNopsFragment &F, unsigned FragmentSize, @@ -1858,6 +1912,18 @@ Error MCCASBuilder::buildFragment(const MCFragment &F, unsigned Size, return Error::success(); \ } #include "llvm/MCCAS/MCCASObjectV1.def" + case MCFragment::FT_Relaxable: + case MCFragment::FT_Data: + case MCFragment::FT_Align: + case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: + case MCFragment::FT_LEB: { + auto GF = MCGenericFragmentRef::create(*this, F, Size, FragmentContents); + if (!GF) + return GF.takeError(); + addNode(*GF); + return Error::success(); + } } llvm_unreachable("unknown fragment"); } @@ -1984,6 +2050,14 @@ Error MCDataFragmentMerger::emitMergedFragments() { return E; break; } + case MCFragment::FT_Relaxable: + case MCFragment::FT_Data: + case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: + case MCFragment::FT_LEB: { + FragmentData.append(CandidateContents); + break; + } default: llvm_unreachable("other framgents should not be added"); } @@ -2861,6 +2935,11 @@ static ArrayRef getFragmentContents(const MCFragment &Fragment) { cast(Fragment); return SF.getContents(); } + case MCFragment::FT_Relaxable: + case MCFragment::FT_Data: + case MCFragment::FT_Align: + case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: case MCFragment::FT_LEB: { return Fragment.getContents(); } @@ -3602,6 +3681,9 @@ Expected MCCASReader::materializeAtom(cas::ObjectRef ID, return F->materialize(*Stream); if (auto F = MergedFragmentRef::Cast(*Node)) return F->materialize(*Stream); + if (auto F = MCGenericFragmentRef::Cast(*Node)) { + return F->materialize(F->FragType, *this, Stream); + } return createStringError(inconvertibleErrorCode(), "unsupported CAS node for fragment"); From e932c21822d8e4a357783001e73840566e7e8785 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Fri, 25 Jul 2025 00:16:05 -0700 Subject: [PATCH 35/39] Revert "WIP fix MCCAS, builds but round trip verification error due to FragType not staying the same after materialization, does it not get saved?" This reverts commit 36becd86d27634b5dcfde104a98e4a67f6a80cd0. --- llvm/include/llvm/MCCAS/MCCASObjectV1.def | 1 - llvm/include/llvm/MCCAS/MCCASObjectV1.h | 57 ---------- llvm/lib/MCCAS/MCCASObjectV1.cpp | 122 ++++------------------ 3 files changed, 20 insertions(+), 160 deletions(-) diff --git a/llvm/include/llvm/MCCAS/MCCASObjectV1.def b/llvm/include/llvm/MCCAS/MCCASObjectV1.def index 5e7667ad8a713..076ed1e2e409e 100644 --- a/llvm/include/llvm/MCCAS/MCCASObjectV1.def +++ b/llvm/include/llvm/MCCAS/MCCASObjectV1.def @@ -85,4 +85,3 @@ MCFRAGMENT_NODE_REF(MCCVDefRangeFragment, FT_CVDefRange, mc:cv_def_range) #undef MCFRAGMENT_NODE_REF #endif /* MCFRAGMENT_NODE_REF */ - diff --git a/llvm/include/llvm/MCCAS/MCCASObjectV1.h b/llvm/include/llvm/MCCAS/MCCASObjectV1.h index fef193b38aeb8..6cce778a8e803 100644 --- a/llvm/include/llvm/MCCAS/MCCASObjectV1.h +++ b/llvm/include/llvm/MCCAS/MCCASObjectV1.h @@ -418,63 +418,6 @@ class SpecificRef : public MCObjectProxy { }; #include "llvm/MCCAS/MCCASObjectV1.def" -class MCGenericFragmentRef : public SpecificRef { - using SpecificRefT = SpecificRef; - friend class SpecificRef; - -public: - MCGenericFragmentRef(SpecificRefT ST, MCFragment::FragmentType FragType) - : SpecificRef(ST), FragType(FragType) {} - MCFragment::FragmentType FragType; - static constexpr StringLiteral KindString = "mc:generic_fragment"; - static Expected create(MCCASBuilder &MB, - const MCFragment &Fragment, - unsigned FragmentSize, - ArrayRef FragmentContents); - static Expected get(Expected Ref, - MCFragment::FragmentType FragType) { - auto Specific = SpecificRefT::getSpecific(std::move(Ref)); - if (!Specific) - return Specific.takeError(); - return MCGenericFragmentRef(*Specific, FragType); - } - static Expected get(const MCSchema &Schema, - cas::ObjectRef ID, - MCFragment::FragmentType FragType) { - return get(Schema.get(ID), FragType); - } - static std::optional Cast(MCObjectProxy Ref) { - auto Specific = SpecificRefT::Cast(Ref); - if (!Specific) - return std::nullopt; - return MCGenericFragmentRef(*Specific); - } - Expected materialize(const MCFragment::FragmentType FragType, - MCCASReader &Reader, - raw_ostream *Stream) const; - - static Expected - createGenericAlignFragmentRef(MCCASBuilder &MB, const MCFragment &F, - unsigned FragmentSize, - ArrayRef FragmentContents); - - static Expected - createGenericLEBFragmentRef(MCCASBuilder &MB, const MCFragment &F, - unsigned FragmentSize, - ArrayRef FragmentContents); - - Expected - materializeGenericAlignFragmentRef(MCCASReader &Reader, - raw_ostream *Stream) const; - - Expected - materializeGenericLEBFragmentRef(MCCASReader &Reader, - raw_ostream *Stream) const; - -private: - explicit MCGenericFragmentRef(SpecificRefT Ref) : SpecificRefT(Ref) {} -}; - class PaddingRef : public SpecificRef { using SpecificRefT = SpecificRef; friend class SpecificRef; diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 9859af495f35c..e62aa66f2d871 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -48,7 +48,6 @@ constexpr StringLiteral PaddingRef::KindString; #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ constexpr StringLiteral MCFragmentName##Ref::KindString; #include "llvm/MCCAS/MCCASObjectV1.def" -constexpr StringLiteral MCGenericFragmentRef::KindString; constexpr StringLiteral DebugInfoSectionRef::KindString; void MCSchema::anchor() {} @@ -173,7 +172,6 @@ Error MCSchema::fillCache() { PaddingRef::KindString, MCAssemblerRef::KindString, DebugInfoSectionRef::KindString, - MCGenericFragmentRef::KindString, #define CASV1_SIMPLE_DATA_REF(RefName, IdentifierName) RefName::KindString, #define CASV1_SIMPLE_GROUP_REF(RefName, IdentifierName) RefName::KindString, #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ @@ -1533,16 +1531,16 @@ Expected AtomRef::materialize(MCCASReader &Reader, return Size; } -Expected -MCGenericFragmentRef::createGenericAlignFragmentRef( - MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, - ArrayRef FragmentContents) { +Expected +MCAlignFragmentRef::create(MCCASBuilder &MB, const MCAlignFragment &F, + unsigned FragmentSize, + ArrayRef FragmentContents) { Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); - uint64_t Count = FragmentSize / F.getAlignFillLen(); - if (F.hasAlignEmitNops()) { + uint64_t Count = FragmentSize / F.getFillLen(); + if (F.hasEmitNops()) { // Write 0 as size and use backend to emit nop. writeVBR8(0, B->Data); if (!MB.Asm.getBackend().writeNopData(MB.FragmentOS, Count, @@ -1550,16 +1548,17 @@ MCGenericFragmentRef::createGenericAlignFragmentRef( report_fatal_error("unable to write nop sequence of " + Twine(Count) + " bytes"); B->Data.append(MB.FragmentData); - return get(B->build(), MCFragment::FT_Align); + return get(B->build()); } writeVBR8(Count, B->Data); - writeVBR8(F.getAlignFill(), B->Data); - writeVBR8(F.getAlignFillLen(), B->Data); - return get(B->build(), MCFragment::FT_Align); + writeVBR8(F.getFill(), B->Data); + writeVBR8(F.getFillLen(), B->Data); + return get(B->build()); } -Expected MCGenericFragmentRef::materializeGenericAlignFragmentRef( - MCCASReader &Reader, raw_ostream *Stream) const { +Expected MCAlignFragmentRef::materialize(MCCASReader &Reader, + raw_ostream *Stream) const + { uint64_t Count; auto Remaining = getData(); auto Endian = Reader.getEndian(); @@ -1687,76 +1686,23 @@ Expected MCFillFragmentRef::materialize(MCCASReader &Reader, return Size; } -Expected -MCGenericFragmentRef::createGenericLEBFragmentRef( - MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, - ArrayRef FragmentContents) { +Expected +MCLEBFragmentRef::create(MCCASBuilder &MB, const MCLEBFragment &F, + unsigned FragmentSize, + ArrayRef FragmentContents) { Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); llvm::append_range(B->Data, F.getContents()); - return get(B->build(), MCFragment::FT_LEB); + return get(B->build()); } -Expected MCGenericFragmentRef::materializeGenericLEBFragmentRef( - MCCASReader &Reader, raw_ostream *Stream) const { +Expected MCLEBFragmentRef::materialize(MCCASReader &Reader, + raw_ostream *Stream) const { *Stream << getData(); return getData().size(); } -Expected -MCGenericFragmentRef::create(MCCASBuilder &MB, const MCFragment &Fragment, - unsigned int FragmentSize, - ArrayRef FragmentContents) { - auto FragType = Fragment.getKind(); - switch (FragType) { - case MCFragment::FT_Align: - return createGenericAlignFragmentRef(MB, Fragment, FragmentSize, - FragmentContents); - case MCFragment::FT_LEB: - return createGenericLEBFragmentRef(MB, Fragment, FragmentSize, - FragmentContents); - case MCFragment::FT_Relaxable: - case MCFragment::FT_Data: - case MCFragment::FT_Dwarf: - case MCFragment::FT_DwarfFrame: { - Expected B = Builder::startNode(MB.Schema, KindString); - if (!B) - return B.takeError(); - B->Data.append(MB.FragmentData); - B->Data.append(FragmentContents.begin(), FragmentContents.end()); - assert(((MB.FragmentData.empty() && Fragment.getContents().empty()) || - (MB.FragmentData.size() + Fragment.getContents().size() == - FragmentSize)) && - "Size should match"); - return get(B->build(), FragType); - } - default: - llvm_unreachable("Other Fragment Kinds should be handled elsewhere!"); - } -} - -Expected -MCGenericFragmentRef::materialize(const MCFragment::FragmentType FragType, - MCCASReader &Reader, - raw_ostream *Stream) const { - switch (FragType) { - case MCFragment::FT_Align: - return materializeGenericAlignFragmentRef(Reader, Stream); - case MCFragment::FT_LEB: - return materializeGenericLEBFragmentRef(Reader, Stream); - case MCFragment::FT_Relaxable: - case MCFragment::FT_Data: - case MCFragment::FT_Dwarf: - case MCFragment::FT_DwarfFrame: { - *Stream << getData(); - return getData().size(); - } - default: - llvm_unreachable("Other Fragment Kinds should be handled elsewhere!"); - } -} - Expected MCNopsFragmentRef::create(MCCASBuilder &MB, const MCNopsFragment &F, unsigned FragmentSize, @@ -1912,18 +1858,6 @@ Error MCCASBuilder::buildFragment(const MCFragment &F, unsigned Size, return Error::success(); \ } #include "llvm/MCCAS/MCCASObjectV1.def" - case MCFragment::FT_Relaxable: - case MCFragment::FT_Data: - case MCFragment::FT_Align: - case MCFragment::FT_Dwarf: - case MCFragment::FT_DwarfFrame: - case MCFragment::FT_LEB: { - auto GF = MCGenericFragmentRef::create(*this, F, Size, FragmentContents); - if (!GF) - return GF.takeError(); - addNode(*GF); - return Error::success(); - } } llvm_unreachable("unknown fragment"); } @@ -2050,14 +1984,6 @@ Error MCDataFragmentMerger::emitMergedFragments() { return E; break; } - case MCFragment::FT_Relaxable: - case MCFragment::FT_Data: - case MCFragment::FT_Dwarf: - case MCFragment::FT_DwarfFrame: - case MCFragment::FT_LEB: { - FragmentData.append(CandidateContents); - break; - } default: llvm_unreachable("other framgents should not be added"); } @@ -2935,11 +2861,6 @@ static ArrayRef getFragmentContents(const MCFragment &Fragment) { cast(Fragment); return SF.getContents(); } - case MCFragment::FT_Relaxable: - case MCFragment::FT_Data: - case MCFragment::FT_Align: - case MCFragment::FT_Dwarf: - case MCFragment::FT_DwarfFrame: case MCFragment::FT_LEB: { return Fragment.getContents(); } @@ -3681,9 +3602,6 @@ Expected MCCASReader::materializeAtom(cas::ObjectRef ID, return F->materialize(*Stream); if (auto F = MergedFragmentRef::Cast(*Node)) return F->materialize(*Stream); - if (auto F = MCGenericFragmentRef::Cast(*Node)) { - return F->materialize(F->FragType, *this, Stream); - } return createStringError(inconvertibleErrorCode(), "unsupported CAS node for fragment"); From dea980155fe5e14acae53134e1d7bc5c27747c89 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Fri, 25 Jul 2025 04:04:01 -0700 Subject: [PATCH 36/39] WIP MCCAS MaskRay Fix, works for small cpp file but not on bootstrap build --- llvm/include/llvm/MCCAS/MCCASObjectV1.def | 6 +++ llvm/include/llvm/MCCAS/MCCASObjectV1.h | 4 +- llvm/lib/MCCAS/MCCASObjectV1.cpp | 61 ++++++++++++----------- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/llvm/include/llvm/MCCAS/MCCASObjectV1.def b/llvm/include/llvm/MCCAS/MCCASObjectV1.def index 076ed1e2e409e..aab14eda7012f 100644 --- a/llvm/include/llvm/MCCAS/MCCASObjectV1.def +++ b/llvm/include/llvm/MCCAS/MCCASObjectV1.def @@ -72,15 +72,21 @@ CASV1_SIMPLE_GROUP_REF(DIEDedupeTopLevelRef, mc:debug_DIE_Dedupe_top_level) #ifdef MCFRAGMENT_NODE_REF #ifndef MCFRAGMENT_ENCODED_FRAGMENT_ONLY +MCFRAGMENT_NODE_REF(MCAlignFragment, FT_Align, mc:align) MCFRAGMENT_NODE_REF(MCBoundaryAlignFragment, FT_BoundaryAlign, mc:boundary_align) MCFRAGMENT_NODE_REF(MCCVInlineLineTableFragment, FT_CVInlineLines, mc:cv_inline_lines) MCFRAGMENT_NODE_REF(MCFillFragment, FT_Fill, mc:fill) +MCFRAGMENT_NODE_REF(MCLEBFragment, FT_LEB, mc:leb) MCFRAGMENT_NODE_REF(MCNopsFragment, FT_Nops, mc:nops) MCFRAGMENT_NODE_REF(MCOrgFragment, FT_Org, mc:org) MCFRAGMENT_NODE_REF(MCSymbolIdFragment, FT_SymbolId, mc:symbol_id) #endif /* MCFRAGMENT_ENCODED_FRAGMENT_ONLY */ #undef MCFRAGMENT_ENCODED_FRAGMENT_ONLY +MCFRAGMENT_NODE_REF(MCDataFragment, FT_Data, mc:data) +MCFRAGMENT_NODE_REF(MCRelaxableFragment, FT_Relaxable, mc:relaxable) +MCFRAGMENT_NODE_REF(MCDwarfLineAddrFragment, FT_Dwarf, mc:dwarf) +MCFRAGMENT_NODE_REF(MCDwarfCallFrameFragment, FT_DwarfFrame, mc:dwarf_frame) MCFRAGMENT_NODE_REF(MCCVDefRangeFragment, FT_CVDefRange, mc:cv_def_range) #undef MCFRAGMENT_NODE_REF diff --git a/llvm/include/llvm/MCCAS/MCCASObjectV1.h b/llvm/include/llvm/MCCAS/MCCASObjectV1.h index 6cce778a8e803..2aaf858ebd247 100644 --- a/llvm/include/llvm/MCCAS/MCCASObjectV1.h +++ b/llvm/include/llvm/MCCAS/MCCASObjectV1.h @@ -392,7 +392,7 @@ class SpecificRef : public MCObjectProxy { public: \ static constexpr StringLiteral KindString = #MCEnumIdentifier; \ static Expected \ - create(MCCASBuilder &MB, const MCFragmentName &Fragment, \ + create(MCCASBuilder &MB, const MCFragment &Fragment, \ unsigned FragmentSize, ArrayRef FragmentContents); \ static Expected get(Expected Ref) { \ auto Specific = SpecificRefT::getSpecific(std::move(Ref)); \ @@ -404,7 +404,7 @@ class SpecificRef : public MCObjectProxy { cas::ObjectRef ID) { \ return get(Schema.get(ID)); \ } \ - static std::optional Cast(MCObjectProxy Ref) { \ + static std::optional Cast(MCObjectProxy Ref) { \ auto Specific = SpecificRefT::Cast(Ref); \ if (!Specific) \ return std::nullopt; \ diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index e62aa66f2d871..84e37d12d4b4f 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -1532,15 +1532,15 @@ Expected AtomRef::materialize(MCCASReader &Reader, } Expected -MCAlignFragmentRef::create(MCCASBuilder &MB, const MCAlignFragment &F, +MCAlignFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, ArrayRef FragmentContents) { Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); - uint64_t Count = FragmentSize / F.getFillLen(); - if (F.hasEmitNops()) { + uint64_t Count = FragmentSize / F.getAlignFillLen(); + if (F.hasAlignEmitNops()) { // Write 0 as size and use backend to emit nop. writeVBR8(0, B->Data); if (!MB.Asm.getBackend().writeNopData(MB.FragmentOS, Count, @@ -1551,8 +1551,8 @@ MCAlignFragmentRef::create(MCCASBuilder &MB, const MCAlignFragment &F, return get(B->build()); } writeVBR8(Count, B->Data); - writeVBR8(F.getFill(), B->Data); - writeVBR8(F.getFillLen(), B->Data); + writeVBR8(F.getAlignFill(), B->Data); + writeVBR8(F.getAlignFillLen(), B->Data); return get(B->build()); } @@ -1598,9 +1598,10 @@ Expected MCAlignFragmentRef::materialize(MCCASReader &Reader, return Count * ValueSize; } -Expected MCBoundaryAlignFragmentRef::create( - MCCASBuilder &MB, const MCBoundaryAlignFragment &F, unsigned FragmentSize, - ArrayRef FragmentContents) { +Expected +MCBoundaryAlignFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, + unsigned FragmentSize, + ArrayRef FragmentContents) { Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); @@ -1619,9 +1620,10 @@ MCBoundaryAlignFragmentRef::materialize(MCCASReader &Reader, return getData().size(); } -Expected MCCVInlineLineTableFragmentRef::create( - MCCASBuilder &MB, const MCCVInlineLineTableFragment &F, - unsigned FragmentSize, ArrayRef FragmentContents) { +Expected +MCCVInlineLineTableFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, + unsigned FragmentSize, + ArrayRef FragmentContents) { Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); @@ -1637,15 +1639,16 @@ MCCVInlineLineTableFragmentRef::materialize(MCCASReader &Reader, } Expected -MCFillFragmentRef::create(MCCASBuilder &MB, const MCFillFragment &F, +MCFillFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, ArrayRef FragmentContents) { + auto *FillFrag = dyn_cast(&F); Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); writeVBR8(FragmentSize, B->Data); - writeVBR8(F.getValue(), B->Data); - writeVBR8(F.getValueSize(), B->Data); + writeVBR8(FillFrag->getValue(), B->Data); + writeVBR8(FillFrag->getValueSize(), B->Data); return get(B->build()); } @@ -1687,7 +1690,7 @@ Expected MCFillFragmentRef::materialize(MCCASReader &Reader, } Expected -MCLEBFragmentRef::create(MCCASBuilder &MB, const MCLEBFragment &F, +MCLEBFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, ArrayRef FragmentContents) { Expected B = Builder::startNode(MB.Schema, KindString); @@ -1704,14 +1707,15 @@ Expected MCLEBFragmentRef::materialize(MCCASReader &Reader, } Expected -MCNopsFragmentRef::create(MCCASBuilder &MB, const MCNopsFragment &F, +MCNopsFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, ArrayRef FragmentContents) { + auto *NopsFrag = dyn_cast(&F); Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); - int64_t NumBytes = F.getNumBytes(); - int64_t ControlledNopLength = F.getControlledNopLength(); + int64_t NumBytes = NopsFrag->getNumBytes(); + int64_t ControlledNopLength = NopsFrag->getControlledNopLength(); int64_t MaximumNopLength = MB.Asm.getBackend().getMaximumNopSize(*F.getSubtargetInfo()); if (ControlledNopLength > MaximumNopLength) @@ -1740,14 +1744,15 @@ Expected MCNopsFragmentRef::materialize(MCCASReader &Reader, } Expected -MCOrgFragmentRef::create(MCCASBuilder &MB, const MCOrgFragment &F, +MCOrgFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, ArrayRef FragmentContents) { + auto *OrgFrag = dyn_cast(&F); Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); writeVBR8(FragmentSize, B->Data); - writeVBR8((char)F.getValue(), B->Data); + writeVBR8((char)OrgFrag->getValue(), B->Data); return get(B->build()); } @@ -1758,13 +1763,14 @@ Expected MCOrgFragmentRef::materialize(MCCASReader &Reader, } Expected -MCSymbolIdFragmentRef::create(MCCASBuilder &MB, const MCSymbolIdFragment &F, +MCSymbolIdFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, ArrayRef FragmentContents) { + auto *SymbolIDFrag = dyn_cast(&F); Expected B = Builder::startNode(MB.Schema, KindString); if (!B) return B.takeError(); - writeVBR8(F.getSymbol()->getIndex(), B->Data); + writeVBR8(SymbolIDFrag->getSymbol()->getIndex(), B->Data); return get(B->build()); } @@ -1777,7 +1783,7 @@ MCSymbolIdFragmentRef::materialize(MCCASReader &Reader, #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ Expected MCFragmentName##Ref::create( \ - MCCASBuilder &MB, const MCFragmentName &F, unsigned FragmentSize, \ + MCCASBuilder &MB, const MCFragment &F, unsigned FragmentSize, \ ArrayRef FragmentContents) { \ Expected B = Builder::startNode(MB.Schema, KindString); \ if (!B) \ @@ -1850,8 +1856,7 @@ Error MCCASBuilder::buildFragment(const MCFragment &F, unsigned Size, switch (F.getKind()) { #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ case MCFragment::MCEnumName: { \ - const MCFragmentName &SF = cast(F); \ - auto FN = MCFragmentName##Ref::create(*this, SF, Size, FragmentContents); \ + auto FN = MCFragmentName##Ref::create(*this, F, Size, FragmentContents); \ if (!FN) \ return FN.takeError(); \ addNode(*FN); \ @@ -1922,7 +1927,8 @@ Error MCDataFragmentMerger::tryMerge(const MCFragment &F, unsigned Size, static Error writeAlignFragment(MCCASBuilder &Builder, const MCFragment &AF, raw_ostream &OS, unsigned FragmentSize) { - uint64_t Count = FragmentSize / AF.getAlignFillLen(); + OS << StringRef(AF.getContents().data(), AF.getContents().size()); + uint64_t Count = (FragmentSize - AF.getFixedSize()) / AF.getAlignFillLen(); if (AF.hasAlignEmitNops()) { if (!Builder.Asm.getBackend().writeNopData(OS, Count, AF.getSubtargetInfo())) @@ -2851,8 +2857,7 @@ static ArrayRef getFragmentContents(const MCFragment &Fragment) { switch (Fragment.getKind()) { #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ case MCFragment::MCEnumName: { \ - const MCFragmentName &SF = cast(Fragment); \ - return SF.getContents(); \ + return Fragment.getContents(); \ } #define MCFRAGMENT_ENCODED_FRAGMENT_ONLY #include "llvm/MCCAS/MCCASObjectV1.def" From 3681cecffd81701743e6ca49451211cd19612edc Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Fri, 25 Jul 2025 10:14:36 -0700 Subject: [PATCH 37/39] Edit MCAlignFragmentRef::create and materialize to match what is there in MCAssembler.cpp writeFragment, FT_Align fragments have data in them now? --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 84e37d12d4b4f..b39bdec2d319f 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -1539,7 +1539,9 @@ MCAlignFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, if (!B) return B.takeError(); - uint64_t Count = FragmentSize / F.getAlignFillLen(); + writeVBR8(FragmentContents.size(), B->Data); + B->Data.append(FragmentContents.begin(), FragmentContents.end()); + uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen(); if (F.hasAlignEmitNops()) { // Write 0 as size and use backend to emit nop. writeVBR8(0, B->Data); @@ -1559,9 +1561,16 @@ MCAlignFragmentRef::create(MCCASBuilder &MB, const MCFragment &F, Expected MCAlignFragmentRef::materialize(MCCASReader &Reader, raw_ostream *Stream) const { - uint64_t Count; + uint64_t Count, FragContentSize; auto Remaining = getData(); auto Endian = Reader.getEndian(); + if (auto E = consumeVBR8(Remaining, FragContentSize)) + return std::move(E); + + *Stream << Remaining.substr(0, FragContentSize); + + Remaining = Remaining.drop_front(FragContentSize); + if (auto E = consumeVBR8(Remaining, Count)) return std::move(E); @@ -2869,6 +2878,9 @@ static ArrayRef getFragmentContents(const MCFragment &Fragment) { case MCFragment::FT_LEB: { return Fragment.getContents(); } + case MCFragment::FT_Align: { + return Fragment.getContents(); + } default: return ArrayRef(); } From 03db9b7c444bc6d52189419ce7e22196f1dc6d8f Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Fri, 25 Jul 2025 10:25:03 -0700 Subject: [PATCH 38/39] Fix getFragmentContents to match what we see in MCAssembler.cpp writeFragment --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index b39bdec2d319f..726aba7b6dcbd 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2862,27 +2862,38 @@ Error MCCASBuilder::createAppleObjCSection() { return finalizeSection(); } -static ArrayRef getFragmentContents(const MCFragment &Fragment) { +static void getFragmentContents(const MCFragment &Fragment, + SmallVectorImpl &FragContents) { switch (Fragment.getKind()) { #define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \ case MCFragment::MCEnumName: { \ - return Fragment.getContents(); \ + FragContents.append(Fragment.getContents().begin(), \ + Fragment.getContents().end()); \ + \ + return; \ } #define MCFRAGMENT_ENCODED_FRAGMENT_ONLY #include "llvm/MCCAS/MCCASObjectV1.def" case MCFragment::FT_CVInlineLines: { const MCCVInlineLineTableFragment &SF = cast(Fragment); - return SF.getContents(); + FragContents.append(SF.getContents().begin(), SF.getContents().end()); + return; } case MCFragment::FT_LEB: { - return Fragment.getContents(); + auto FixedContent = Fragment.getContents(); + auto VarContent = Fragment.getVarContents(); + FragContents.append(FixedContent.begin(), FixedContent.end()); + FragContents.append(VarContent.begin(), VarContent.end()); + return; } case MCFragment::FT_Align: { - return Fragment.getContents(); + FragContents.append(Fragment.getContents().begin(), + Fragment.getContents().end()); + return; } default: - return ArrayRef(); + return; } } @@ -2914,7 +2925,8 @@ partitionFragment(MCAssembler &Asm, SmallVector &Addends, ArrayRef RelocationBuffer, const MCFragment &Fragment, uint64_t &RelocationBufferIndex, bool IsLittleEndian) { - auto FragmentContents = getFragmentContents(Fragment); + SmallVector FragmentContents; + getFragmentContents(Fragment, FragmentContents); /// FragmentIndex: It denotes the index into the FragmentContents that is used /// to copy the data that deduplicates in the \p FinalFragmentContents. uint64_t FragmentIndex = 0; From a52419fa91031a5abfb424d34627f59399e30438 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Fri, 25 Jul 2025 10:42:56 -0700 Subject: [PATCH 39/39] Fix MCAlignFragmentRef Size calc --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 726aba7b6dcbd..253152fea5c4e 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -1577,7 +1577,7 @@ Expected MCAlignFragmentRef::materialize(MCCASReader &Reader, // hasEmitNops. if (!Count) { *Stream << Remaining; - return Remaining.size(); + return Remaining.size() + FragContentSize; } int64_t Value; unsigned ValueSize; @@ -1604,7 +1604,7 @@ Expected MCAlignFragmentRef::materialize(MCCASReader &Reader, break; } } - return Count * ValueSize; + return (Count * ValueSize) + FragContentSize; } Expected