Index: include/llvm/MC/MCAssembler.h =================================================================== --- include/llvm/MC/MCAssembler.h +++ include/llvm/MC/MCAssembler.h @@ -426,7 +426,7 @@ /// \brief Write the necessary bundle padding to the given object writer. /// Expects a fragment \p F containing instructions and its size \p FSize. - void writeFragmentPadding(const MCFragment &F, uint64_t FSize, + void writeFragmentPadding(const MCEncodedFragment &F, uint64_t FSize, MCObjectWriter *OW) const; /// @} @@ -437,8 +437,9 @@ /// \brief 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. -uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F, - uint64_t FOffset, uint64_t FSize); +uint64_t computeBundlePadding(const MCAssembler &Assembler, + const MCEncodedFragment *F, uint64_t FOffset, + uint64_t FSize); } // end namespace llvm Index: include/llvm/MC/MCFragment.h =================================================================== --- include/llvm/MC/MCFragment.h +++ include/llvm/MC/MCFragment.h @@ -56,11 +56,6 @@ bool HasInstructions; private: - /// \brief Should this fragment be aligned to the end of a bundle? - bool AlignToBundleEnd; - - uint8_t BundlePadding; - /// LayoutOrder - The layout order of this fragment. unsigned LayoutOrder; @@ -83,8 +78,7 @@ /// @} protected: - MCFragment(FragmentType Kind, bool HasInstructions, - uint8_t BundlePadding, MCSection *Parent = nullptr); + MCFragment(FragmentType Kind, bool HasInstructions, MCSection *Parent = nullptr); ~MCFragment(); @@ -114,21 +108,6 @@ /// this is false, but specific fragment types may set it to true. bool hasInstructions() const { return HasInstructions; } - /// \brief Should this fragment be placed at the end of an aligned bundle? - bool alignToBundleEnd() const { return AlignToBundleEnd; } - void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } - - /// \brief Get the padding size that must be inserted before this fragment. - /// Used for bundling. By default, no padding is inserted. - /// Note that padding size is restricted to 8 bits. This is an optimization - /// to reduce the amount of space used for each fragment. In practice, larger - /// padding should never be required. - uint8_t getBundlePadding() const { return BundlePadding; } - - /// \brief 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; } - /// \brief Return true if given frgment has FT_Dummy type. bool isDummy() const { return Kind == FT_Dummy; } @@ -138,7 +117,7 @@ class MCDummyFragment : public MCFragment { public: explicit MCDummyFragment(MCSection *Sec) - : MCFragment(FT_Dummy, false, 0, Sec) {} + : MCFragment(FT_Dummy, false, Sec) {} static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; } }; @@ -147,10 +126,19 @@ /// data. /// class MCEncodedFragment : public MCFragment { + /// \brief Should this fragment be aligned to the end of a bundle? + bool AlignToBundleEnd = false; + + uint8_t BundlePadding = 0; + protected: MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions, MCSection *Sec) - : MCFragment(FType, HasInstructions, 0, Sec) {} + : MCFragment(FType, HasInstructions, Sec) {} + + /// STI - The MCSubtargetInfo in effect when the instruction was encoded. + /// must be non-null for instructions. + const MCSubtargetInfo *STI = nullptr; public: static bool classof(const MCFragment *F) { @@ -164,6 +152,32 @@ return true; } } + + /// \brief Should this fragment be placed at the end of an aligned bundle? + bool alignToBundleEnd() const { return AlignToBundleEnd; } + void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + + /// \brief Get the padding size that must be inserted before this fragment. + /// Used for bundling. By default, no padding is inserted. + /// Note that padding size is restricted to 8 bits. This is an optimization + /// to reduce the amount of space used for each fragment. In practice, larger + /// padding should never be required. + uint8_t getBundlePadding() const { return BundlePadding; } + + /// \brief 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; } + + /// Record that the fragment contains instructions with the MCSubtargetInfo in + /// effect when the instruction was encoded. + void setHasInstructions(const MCSubtargetInfo &STI) { + HasInstructions = true; + this->STI = &STI; + } }; /// Interface implemented by fragments that contain encoded instructions and/or @@ -201,16 +215,8 @@ : MCEncodedFragmentWithContents(FType, HasInstructions, Sec) {} - /// STI - The MCSubtargetInfo in effect when the instruction was encoded. - /// must be non-null for instructions. - const MCSubtargetInfo *STI = nullptr; - public: - /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. - /// Guaranteed to be non-null if hasInstructions() == true - const MCSubtargetInfo *getSubtargetInfo() const { return STI; } - using const_fixup_iterator = SmallVectorImpl::const_iterator; using fixup_iterator = SmallVectorImpl::iterator; @@ -237,13 +243,6 @@ MCDataFragment(MCSection *Sec = nullptr) : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {} - /// Record that the fragment contains instructions with the MCSubtargetInfo in - /// effect when the instruction was encoded. - void setHasInstructions(const MCSubtargetInfo &STI) { - HasInstructions = true; - this->STI = &STI; - } - static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; } @@ -309,7 +308,7 @@ public: MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, unsigned MaxBytesToEmit, MCSection *Sec = nullptr) - : MCFragment(FT_Align, false, 0, Sec), Alignment(Alignment), + : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false), Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} @@ -379,7 +378,7 @@ }; MCPaddingFragment(MCSection *Sec = nullptr) - : MCFragment(FT_Padding, false, 0, Sec), PaddingPoliciesMask(PFK_None), + : MCFragment(FT_Padding, false, Sec), PaddingPoliciesMask(PFK_None), IsInsertionPoint(false), Size(UINT64_C(0)), InstInfo({false, MCInst(), false, {0}}) {} @@ -439,7 +438,7 @@ public: MCFillFragment(uint8_t Value, const MCExpr &Size, SMLoc Loc, MCSection *Sec = nullptr) - : MCFragment(FT_Fill, false, 0, Sec), Value(Value), Size(Size), Loc(Loc) { + : MCFragment(FT_Fill, false, Sec), Value(Value), Size(Size), Loc(Loc) { } uint8_t getValue() const { return Value; } @@ -465,7 +464,7 @@ public: MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc, MCSection *Sec = nullptr) - : MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value), Loc(Loc) {} + : MCFragment(FT_Org, false, Sec), Offset(&Offset), Value(Value), Loc(Loc) {} /// \name Accessors /// @{ @@ -494,7 +493,7 @@ public: MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) - : MCFragment(FT_LEB, false, 0, Sec), Value(&Value_), IsSigned(IsSigned_) { + : MCFragment(FT_LEB, false, Sec), Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } @@ -529,7 +528,7 @@ public: MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, MCSection *Sec = nullptr) - : MCFragment(FT_Dwarf, false, 0, Sec), LineDelta(LineDelta), + : MCFragment(FT_Dwarf, false, Sec), LineDelta(LineDelta), AddrDelta(&AddrDelta) { Contents.push_back(0); } @@ -560,7 +559,7 @@ public: MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) - : MCFragment(FT_DwarfFrame, false, 0, Sec), AddrDelta(&AddrDelta) { + : MCFragment(FT_DwarfFrame, false, Sec), AddrDelta(&AddrDelta) { Contents.push_back(0); } @@ -585,7 +584,7 @@ public: MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr) - : MCFragment(FT_SymbolId, false, 0, Sec), Sym(Sym) {} + : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {} /// \name Accessors /// @{ @@ -619,7 +618,7 @@ unsigned StartLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, MCSection *Sec = nullptr) - : MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId), + : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId), StartFileId(StartFileId), StartLineNum(StartLineNum), FnStartSym(FnStartSym), FnEndSym(FnEndSym) {} Index: lib/MC/MCAssembler.cpp =================================================================== --- lib/MC/MCAssembler.cpp +++ lib/MC/MCAssembler.cpp @@ -411,17 +411,18 @@ if (Assembler.isBundlingEnabled() && F->hasInstructions()) { assert(isa(F) && "Only MCEncodedFragment implementations have instructions"); - uint64_t FSize = Assembler.computeFragmentSize(*this, *F); + MCEncodedFragment *EF = cast(F); + uint64_t FSize = Assembler.computeFragmentSize(*this, *EF); if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize()) report_fatal_error("Fragment can't be larger than a bundle size"); - uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, F, - F->Offset, FSize); + uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, EF, + EF->Offset, FSize); if (RequiredBundlePadding > UINT8_MAX) report_fatal_error("Padding cannot exceed 255 bytes"); - F->setBundlePadding(static_cast(RequiredBundlePadding)); - F->Offset += RequiredBundlePadding; + EF->setBundlePadding(static_cast(RequiredBundlePadding)); + EF->Offset += RequiredBundlePadding; } } @@ -435,18 +436,19 @@ } } -void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize, +void MCAssembler::writeFragmentPadding(const MCEncodedFragment &EF, + uint64_t FSize, MCObjectWriter *OW) const { // Should NOP padding be written out before this fragment? - unsigned BundlePadding = F.getBundlePadding(); + unsigned BundlePadding = EF.getBundlePadding(); if (BundlePadding > 0) { assert(isBundlingEnabled() && "Writing bundle padding with disabled bundling"); - assert(F.hasInstructions() && + assert(EF.hasInstructions() && "Writing bundle padding for a fragment without instructions"); unsigned TotalLength = BundlePadding + static_cast(FSize); - if (F.alignToBundleEnd() && TotalLength > getBundleAlignSize()) { + 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 @@ -457,8 +459,8 @@ // ^-------------------^ <- TotalLength unsigned DistanceToBoundary = TotalLength - getBundleAlignSize(); if (!getBackend().writeNopData(DistanceToBoundary, OW)) - report_fatal_error("unable to write NOP sequence of " + - Twine(DistanceToBoundary) + " bytes"); + report_fatal_error("unable to write NOP sequence of " + + Twine(DistanceToBoundary) + " bytes"); BundlePadding -= DistanceToBoundary; } if (!getBackend().writeNopData(BundlePadding, OW)) @@ -475,7 +477,8 @@ // FIXME: Embed in fragments instead? uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); - Asm.writeFragmentPadding(F, FragmentSize, OW); + if (const MCEncodedFragment *EF = dyn_cast(&F)) + Asm.writeFragmentPadding(*EF, FragmentSize, OW); // This variable (and its dummy usage) is to participate in the assert at // the end of the function. Index: lib/MC/MCELFStreamer.cpp =================================================================== --- lib/MC/MCELFStreamer.cpp +++ lib/MC/MCELFStreamer.cpp @@ -535,6 +535,7 @@ MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); insert(CEIF); CEIF->getContents().append(Code.begin(), Code.end()); + CEIF->setHasInstructions(STI); return; } else { DF = new MCDataFragment(); Index: lib/MC/MCFragment.cpp =================================================================== --- lib/MC/MCFragment.cpp +++ lib/MC/MCFragment.cpp @@ -188,7 +188,7 @@ } uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler, - const MCFragment *F, + const MCEncodedFragment *F, uint64_t FOffset, uint64_t FSize) { uint64_t BundleSize = Assembler.getBundleAlignSize(); assert(BundleSize > 0 && @@ -235,10 +235,9 @@ MCFragment::~MCFragment() = default; MCFragment::MCFragment(FragmentType Kind, bool HasInstructions, - uint8_t BundlePadding, MCSection *Parent) - : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false), - BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr), - Offset(~UINT64_C(0)) { + MCSection *Parent) + : Kind(Kind), HasInstructions(HasInstructions), + Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) { if (Parent && !isDummy()) Parent->getFragmentList().push_back(this); } @@ -332,10 +331,11 @@ case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break; } - OS << "(getBundlePadding()) << ">"; + OS << "(this)) + OS << " BundlePadding:" << static_cast(EF->getBundlePadding()); + OS << ">"; switch (getKind()) { case MCFragment::FT_Align: {