From 2930a87e589e61747900ebdc36bb4fe33eed9da9 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 29 Jun 2025 21:27:00 -0700 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?= =?UTF-8?q?l=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.5-bogner --- llvm/include/llvm/MC/MCFragment.h | 121 +++++++---------- llvm/include/llvm/MC/MCSection.h | 5 + llvm/lib/MC/MCAssembler.cpp | 58 ++++---- llvm/lib/MC/MCCodeView.cpp | 12 +- llvm/lib/MC/MCELFStreamer.cpp | 10 +- llvm/lib/MC/MCFragment.cpp | 127 +++++++++++------- llvm/lib/MC/MCObjectStreamer.cpp | 22 ++- llvm/lib/MC/MCSection.cpp | 6 +- llvm/lib/MC/MachObjectWriter.cpp | 5 +- llvm/lib/MC/WinCOFFObjectWriter.cpp | 6 +- .../MCTargetDesc/LoongArchAsmBackend.cpp | 27 ++-- .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 26 ++-- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 2 +- 13 files changed, 227 insertions(+), 200 deletions(-) diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h index 2affa85c744ba..789f9a0e602b2 100644 --- a/llvm/include/llvm/MC/MCFragment.h +++ b/llvm/include/llvm/MC/MCFragment.h @@ -30,6 +30,9 @@ class MCSection; class MCSubtargetInfo; class MCSymbol; +// Represents a contiguous segment of code or data within a section. Its size is +// determined by MCAssembler::layout. All subclasses (except +// MCRelaxableFragment, which stores a MCInst) must have trivial destructors. class MCFragment { friend class MCAssembler; friend class MCObjectStreamer; @@ -86,12 +89,6 @@ class MCFragment { MCFragment(const MCFragment &) = delete; MCFragment &operator=(const MCFragment &) = delete; - /// Destroys the current fragment. - /// - /// This must be used instead of delete as MCFragment is non-virtual. - /// This method will dispatch to the appropriate subclass. - LLVM_ABI void destroy(); - MCFragment *getNext() const { return Next; } FragmentType getKind() const { return Kind; } @@ -113,10 +110,7 @@ class MCFragment { /// Interface implemented by fragments that contain encoded instructions and/or /// data. -/// class MCEncodedFragment : public MCFragment { - uint8_t BundlePadding = 0; - protected: MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions) : MCFragment(FType, HasInstructions) {} @@ -125,6 +119,13 @@ class MCEncodedFragment : public MCFragment { /// It must be non-null for instructions. const MCSubtargetInfo *STI = nullptr; +private: + uint32_t ContentStart = 0; + uint32_t ContentSize = 0; + uint32_t FixupStart = 0; + uint32_t FixupSize = 0; + uint8_t BundlePadding = 0; + public: static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); @@ -136,6 +137,7 @@ class MCEncodedFragment : public MCFragment { case MCFragment::FT_Dwarf: case MCFragment::FT_DwarfFrame: case MCFragment::FT_PseudoProbe: + case MCFragment::FT_CVInlineLines: return true; } } @@ -165,48 +167,33 @@ class MCEncodedFragment : public MCFragment { HasInstructions = true; this->STI = &STI; } -}; -/// Interface implemented by fragments that contain encoded instructions and/or -/// data and also have fixups registered. -/// -template -class MCEncodedFragmentWithFixups : public MCEncodedFragment { - SmallVector Contents; - - /// The list of fixups in this fragment. - SmallVector Fixups; - -protected: - MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, - bool HasInstructions) - : MCEncodedFragment(FType, HasInstructions) {} - -public: - SmallVectorImpl &getContents() { return Contents; } - const SmallVectorImpl &getContents() const { return Contents; } - - void appendContents(ArrayRef C) { Contents.append(C.begin(), C.end()); } - void appendContents(size_t Num, char Elt) { Contents.append(Num, Elt); } - void setContents(ArrayRef C) { Contents.assign(C.begin(), C.end()); } - - void addFixup(MCFixup Fixup) { Fixups.push_back(Fixup); } - SmallVectorImpl &getFixups() { return Fixups; } - const SmallVectorImpl &getFixups() const { return Fixups; } - - static bool classof(const MCFragment *F) { - MCFragment::FragmentType Kind = F->getKind(); - return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data || - Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf || - Kind == MCFragment::FT_DwarfFrame; - } + // Content-related functions manage parent's storage using ContentStart and + // ContentSize. + void clearContents() { ContentSize = 0; } + SmallVectorImpl &getContentsForAppending(); + void doneAppending(); + void appendContents(ArrayRef Contents); + void appendContents(size_t Num, char Elt); + void setContents(ArrayRef Contents); + MutableArrayRef getContents(); + ArrayRef getContents() const; + + // Fixup-related functions manage parent's storage using FixupStart and + // FixupSize. + void clearFixups() { FixupSize = 0; } + void addFixup(MCFixup Fixup); + void appendFixups(ArrayRef Fixups); + void setFixups(ArrayRef Fixups); + MutableArrayRef getFixups(); + ArrayRef getFixups() const; }; /// Fragment for data and encoded instructions. /// -class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { +class MCDataFragment : public MCEncodedFragment { public: - MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {} + MCDataFragment() : MCEncodedFragment(FT_Data, false) {} static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; @@ -219,13 +206,13 @@ class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { /// 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 MCEncodedFragmentWithFixups<8, 1> { +class MCRelaxableFragment : public MCEncodedFragment { /// The instruction this is a fragment for. MCInst Inst; public: MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI) - : MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) { + : MCEncodedFragment(FT_Relaxable, true), Inst(Inst) { this->STI = &STI; } @@ -374,7 +361,7 @@ class MCOrgFragment : public MCFragment { } }; -class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> { +class MCLEBFragment final : public MCEncodedFragment { /// True if this is a sleb128, false if uleb128. bool IsSigned; @@ -383,24 +370,19 @@ class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> { public: MCLEBFragment(const MCExpr &Value, bool IsSigned) - : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false), IsSigned(IsSigned), - Value(&Value) { - getContents().push_back(0); - } + : 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 MCEncodedFragmentWithFixups<8, 1> { +class MCDwarfLineAddrFragment : public MCEncodedFragment { /// The value of the difference between the two line numbers /// between two .loc dwarf directives. int64_t LineDelta; @@ -411,8 +393,8 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> { public: MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta) - : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false), - LineDelta(LineDelta), AddrDelta(&AddrDelta) {} + : MCEncodedFragment(FT_Dwarf, false), LineDelta(LineDelta), + AddrDelta(&AddrDelta) {} int64_t getLineDelta() const { return LineDelta; } @@ -423,15 +405,14 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> { } }; -class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> { +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) - : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false), - AddrDelta(&AddrDelta) {} + : MCEncodedFragment(FT_DwarfFrame, false), AddrDelta(&AddrDelta) {} const MCExpr &getAddrDelta() const { return *AddrDelta; } void setAddrDelta(const MCExpr *E) { AddrDelta = E; } @@ -459,13 +440,12 @@ class MCSymbolIdFragment : public MCFragment { /// Fragment representing the binary annotations produced by the /// .cv_inline_linetable directive. -class MCCVInlineLineTableFragment : public MCFragment { +class MCCVInlineLineTableFragment : public MCEncodedFragment { unsigned SiteFuncId; unsigned StartFileId; unsigned StartLineNum; const MCSymbol *FnStartSym; const MCSymbol *FnEndSym; - SmallString<8> Contents; /// CodeViewContext has the real knowledge about this format, so let it access /// our members. @@ -475,23 +455,20 @@ class MCCVInlineLineTableFragment : public MCFragment { MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId, unsigned StartLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) - : MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId), + : MCEncodedFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId), StartFileId(StartFileId), StartLineNum(StartLineNum), FnStartSym(FnStartSym), FnEndSym(FnEndSym) {} const MCSymbol *getFnStartSym() const { return FnStartSym; } const MCSymbol *getFnEndSym() const { return FnEndSym; } - SmallString<8> &getContents() { return Contents; } - const SmallString<8> &getContents() const { return Contents; } - static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_CVInlineLines; } }; /// Fragment representing the .cv_def_range directive. -class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> { +class MCCVDefRangeFragment : public MCEncodedFragment { ArrayRef> Ranges; StringRef FixedSizePortion; @@ -503,8 +480,9 @@ class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> { MCCVDefRangeFragment( ArrayRef> Ranges, StringRef FixedSizePortion) - : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false), - Ranges(Ranges), FixedSizePortion(FixedSizePortion) {} + : MCEncodedFragment(FT_CVDefRange, false), + Ranges(Ranges.begin(), Ranges.end()), + FixedSizePortion(FixedSizePortion) {} ArrayRef> getRanges() const { return Ranges; @@ -556,15 +534,14 @@ class MCBoundaryAlignFragment : public MCFragment { } }; -class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> { +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) - : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false), - AddrDelta(AddrDelta) {} + : MCEncodedFragment(FT_PseudoProbe, false), AddrDelta(AddrDelta) {} const MCExpr &getAddrDelta() const { return *AddrDelta; } diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index a4e391dfb03ea..fb59c74b7c484 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -39,6 +39,7 @@ class LLVM_ABI MCSection { public: friend MCAssembler; friend MCObjectStreamer; + friend class MCEncodedFragment; static constexpr unsigned NonUniqueID = ~0U; enum SectionVariant { @@ -116,6 +117,10 @@ class LLVM_ABI MCSection { // subsections. SmallVector, 1> Subsections; + // Content and fixup storage for fragments + SmallVector ContentStorage; + SmallVector FixupStorage; + protected: // TODO Make Name private when possible. StringRef Name; diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index bd2242af23f7c..f3ad5b6d71b80 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -607,12 +607,14 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, case MCFragment::FT_Data: ++stats::EmittedDataFragments; - OS << cast(F).getContents(); + OS << StringRef(cast(F).getContents().data(), + cast(F).getContents().size()); break; case MCFragment::FT_Relaxable: ++stats::EmittedRelaxableFragments; - OS << cast(F).getContents(); + OS << StringRef(cast(F).getContents().data(), + cast(F).getContents().size()); break; case MCFragment::FT_Fill: { @@ -692,7 +694,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, case MCFragment::FT_LEB: { const MCLEBFragment &LF = cast(F); - OS << LF.getContents(); + OS << StringRef(LF.getContents().data(), LF.getContents().size()); break; } @@ -722,27 +724,27 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, case MCFragment::FT_Dwarf: { const MCDwarfLineAddrFragment &OF = cast(F); - OS << OF.getContents(); + OS << StringRef(OF.getContents().data(), OF.getContents().size()); break; } case MCFragment::FT_DwarfFrame: { const MCDwarfCallFrameFragment &CF = cast(F); - OS << CF.getContents(); + OS << StringRef(CF.getContents().data(), CF.getContents().size()); break; } case MCFragment::FT_CVInlineLines: { const auto &OF = cast(F); - OS << OF.getContents(); + OS << StringRef(OF.getContents().data(), OF.getContents().size()); break; } case MCFragment::FT_CVDefRange: { const auto &DRF = cast(F); - OS << DRF.getContents(); + OS << StringRef(DRF.getContents().data(), DRF.getContents().size()); break; } case MCFragment::FT_PseudoProbe: { const MCPseudoProbeAddrFragment &PF = cast(F); - OS << PF.getContents(); + OS << StringRef(PF.getContents().data(), PF.getContents().size()); break; } } @@ -994,10 +996,11 @@ bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { // Encode the new instruction. F.setInst(Relaxed); - F.getFixups().clear(); - F.getContents().clear(); - getEmitter().encodeInstruction(Relaxed, F.getContents(), F.getFixups(), - *F.getSubtargetInfo()); + SmallVector Data; + SmallVector Fixups; + getEmitter().encodeInstruction(Relaxed, Data, Fixups, *F.getSubtargetInfo()); + F.setContents(Data); + F.setFixups(Fixups); return true; } @@ -1005,8 +1008,7 @@ bool MCAssembler::relaxLEB(MCLEBFragment &LF) { const unsigned OldSize = static_cast(LF.getContents().size()); unsigned PadTo = OldSize; int64_t Value; - SmallVectorImpl &Data = LF.getContents(); - LF.getFixups().clear(); + LF.clearFixups(); // 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. @@ -1027,7 +1029,7 @@ bool MCAssembler::relaxLEB(MCLEBFragment &LF) { if (UseZeroPad) Value = 0; } - Data.clear(); + SmallVector Data; raw_svector_ostream OSE(Data); // The compiler can generate EH table assembly that is impossible to assemble // without either adding padding to an LEB fragment or adding extra padding @@ -1037,7 +1039,8 @@ bool MCAssembler::relaxLEB(MCLEBFragment &LF) { encodeSLEB128(Value, OSE, PadTo); else encodeULEB128(Value, OSE, PadTo); - return OldSize != LF.getContents().size(); + LF.setContents(Data); + return OldSize != Data.size(); } /// Check if the branch crosses the boundary. @@ -1107,19 +1110,19 @@ bool MCAssembler::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF) { return WasRelaxed; MCContext &Context = getContext(); - uint64_t OldSize = DF.getContents().size(); + auto OldSize = DF.getContents().size(); int64_t AddrDelta; bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, *this); assert(Abs && "We created a line delta with an invalid expression"); (void)Abs; int64_t LineDelta; LineDelta = DF.getLineDelta(); - SmallVectorImpl &Data = DF.getContents(); - Data.clear(); - DF.getFixups().clear(); + SmallVector Data; MCDwarfLineAddr::encode(Context, getDWARFLinetableParams(), LineDelta, AddrDelta, Data); + DF.setContents(Data); + DF.clearFixups(); return OldSize != Data.size(); } @@ -1138,12 +1141,11 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF) { return false; } - SmallVectorImpl &Data = DF.getContents(); - uint64_t OldSize = Data.size(); - Data.clear(); - DF.getFixups().clear(); - + auto OldSize = DF.getContents().size(); + SmallVector Data; MCDwarfFrameEmitter::encodeAdvanceLoc(Context, Value, Data); + DF.setContents(Data); + DF.clearFixups(); return OldSize != Data.size(); } @@ -1173,13 +1175,13 @@ bool MCAssembler::relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &PF) { bool Abs = PF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, *this); assert(Abs && "We created a pseudo probe with an invalid expression"); (void)Abs; - SmallVectorImpl &Data = PF.getContents(); - Data.clear(); + SmallVector Data; raw_svector_ostream OSE(Data); - PF.getFixups().clear(); // AddrDelta is a signed integer encodeSLEB128(AddrDelta, OSE, OldSize); + PF.setContents(Data); + PF.clearFixups(); return OldSize != Data.size(); } diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index e05374783d2b4..7a50e5c046147 100644 --- a/llvm/lib/MC/MCCodeView.cpp +++ b/llvm/lib/MC/MCCodeView.cpp @@ -512,7 +512,7 @@ void CodeViewContext::encodeInlineLineTable(const MCAssembler &Asm, MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId); - SmallVectorImpl &Buffer = Frag.getContents(); + SmallVector Buffer; Buffer.clear(); // Clear old contents if we went through relaxation. for (const MCCVLoc &Loc : Locs) { // Exit early if our line table would produce an oversized InlineSiteSym @@ -606,15 +606,14 @@ void CodeViewContext::encodeInlineLineTable(const MCAssembler &Asm, compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer); compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer); + Frag.setContents(Buffer); } void CodeViewContext::encodeDefRange(const MCAssembler &Asm, MCCVDefRangeFragment &Frag) { MCContext &Ctx = Asm.getContext(); - SmallVectorImpl &Contents = Frag.getContents(); - Contents.clear(); - SmallVectorImpl &Fixups = Frag.getFixups(); - Fixups.clear(); + SmallVector Contents; + SmallVector Fixups; raw_svector_ostream OS(Contents); // Compute all the sizes up front. @@ -694,4 +693,7 @@ void CodeViewContext::encodeDefRange(const MCAssembler &Asm, GapStartOffset += GapSize + RangeSize; } } + + Frag.setContents(Contents); + Frag.setFixups(Fixups); } diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index 5a514f12ce549..41be72ebeb9ab 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -449,11 +449,13 @@ void MCELFStreamer::emitInstToData(const MCInst &Inst, // Emit instruction directly into data fragment. size_t FixupStartIndex = DF->getFixups().size(); size_t CodeOffset = DF->getContents().size(); - Assembler.getEmitter().encodeInstruction(Inst, DF->getContents(), - DF->getFixups(), STI); + SmallVector Fixups; + Assembler.getEmitter().encodeInstruction(Inst, DF->getContentsForAppending(), + Fixups, STI); + DF->doneAppending(); + DF->appendFixups(Fixups); - auto Fixups = MutableArrayRef(DF->getFixups()).slice(FixupStartIndex); - for (auto &Fixup : Fixups) { + for (auto &Fixup : MutableArrayRef(DF->getFixups()).slice(FixupStartIndex)) { Fixup.setOffset(Fixup.getOffset() + CodeOffset); if (Fixup.isLinkerRelaxable()) { DF->setLinkerRelaxable(); diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index d8db55c9a5f5d..859ee73447aad 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -28,57 +28,90 @@ MCFragment::MCFragment(FragmentType Kind, bool HasInstructions) : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false), LinkerRelaxable(false), AllowAutoPadding(false) {} -void MCFragment::destroy() { - switch (Kind) { - case FT_Align: - cast(this)->~MCAlignFragment(); - return; - case FT_Data: - cast(this)->~MCDataFragment(); - return; - case FT_Fill: - cast(this)->~MCFillFragment(); - return; - case FT_Nops: - cast(this)->~MCNopsFragment(); - return; - case FT_Relaxable: - cast(this)->~MCRelaxableFragment(); - return; - case FT_Org: - cast(this)->~MCOrgFragment(); - return; - case FT_Dwarf: - cast(this)->~MCDwarfLineAddrFragment(); - return; - case FT_DwarfFrame: - cast(this)->~MCDwarfCallFrameFragment(); - return; - case FT_LEB: - cast(this)->~MCLEBFragment(); - return; - case FT_BoundaryAlign: - cast(this)->~MCBoundaryAlignFragment(); - return; - case FT_SymbolId: - cast(this)->~MCSymbolIdFragment(); - return; - case FT_CVInlineLines: - cast(this)->~MCCVInlineLineTableFragment(); - return; - case FT_CVDefRange: - cast(this)->~MCCVDefRangeFragment(); - return; - case FT_PseudoProbe: - cast(this)->~MCPseudoProbeAddrFragment(); - return; +const MCSymbol *MCFragment::getAtom() const { + return cast(Parent)->getAtom(LayoutOrder); +} + +SmallVectorImpl &MCEncodedFragment::getContentsForAppending() { + SmallVectorImpl &S = getParent()->ContentStorage; + if (ContentSize == 0) { + ContentStart = S.size(); + } else if (ContentStart + ContentSize != S.size()) { + // If not empty and not at the storage end, move to the storage end. + auto I = std::exchange(ContentStart, S.size()); + S.reserve(S.size() + ContentSize); + S.append(S.begin() + I, S.begin() + I + ContentSize); } + return S; } -const MCSymbol *MCFragment::getAtom() const { - return cast(Parent)->getAtom(LayoutOrder); +void MCEncodedFragment::doneAppending() { + ContentSize = getParent()->ContentStorage.size() - ContentStart; } +void MCEncodedFragment::appendContents(ArrayRef Contents) { + getContentsForAppending().append(Contents.begin(), Contents.end()); + doneAppending(); +} + +void MCEncodedFragment::appendContents(size_t Num, char Elt) { + getContentsForAppending().append(Num, Elt); + doneAppending(); +} + +void MCEncodedFragment::setContents(ArrayRef Contents) { + auto &S = getParent()->ContentStorage; + if (Contents.size() > ContentSize) { + ContentStart = S.size(); + S.resize_for_overwrite(S.size() + Contents.size()); + } + ContentSize = Contents.size(); + llvm::copy(Contents, S.begin() + ContentStart); +} + +MutableArrayRef MCEncodedFragment::getContents() { + return MutableArrayRef(getParent()->ContentStorage) + .slice(ContentStart, ContentSize); +} + +ArrayRef MCEncodedFragment::getContents() const { + return ArrayRef(getParent()->ContentStorage).slice(ContentStart, ContentSize); +} + +void MCEncodedFragment::addFixup(MCFixup Fixup) { appendFixups({Fixup}); } + +void MCEncodedFragment::appendFixups(ArrayRef Fixups) { + auto &S = getParent()->FixupStorage; + if (FixupSize == 0) { + FixupStart = S.size(); + } else if (FixupStart + FixupSize != S.size()) { + // If not empty and not at the storage end, move to the storage end. + auto I = std::exchange(FixupStart, S.size()); + S.reserve(S.size() + ContentSize); + S.append(S.begin() + I, S.begin() + I + FixupSize); + } + FixupSize += Fixups.size(); + S.append(Fixups.begin(), Fixups.end()); +} + +void MCEncodedFragment::setFixups(ArrayRef Fixups) { + auto &S = getParent()->FixupStorage; + if (Fixups.size() > FixupSize) { + FixupStart = S.size(); + S.resize_for_overwrite(S.size() + Fixups.size()); + } + FixupSize = Fixups.size(); + llvm::copy(Fixups, S.begin() + FixupStart); +} + +MutableArrayRef MCEncodedFragment::getFixups() { + return MutableArrayRef(getParent()->FixupStorage) + .slice(FixupStart, FixupSize); +} + +ArrayRef MCEncodedFragment::getFixups() const { + return ArrayRef(getParent()->FixupStorage).slice(FixupStart, FixupSize); +} #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MCFragment::dump() const { @@ -132,7 +165,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { const auto *F = cast(this); if (F->isLinkerRelaxable()) OS << " LinkerRelaxable"; - const SmallVectorImpl &Contents = F->getContents(); + auto Contents = F->getContents(); OS << " Size:" << Contents.size() << " ["; for (unsigned i = 0, e = Contents.size(); i != e; ++i) { if (i) OS << ","; diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 3b2bb594675f0..b46e06825ca11 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -63,7 +63,7 @@ void MCObjectStreamer::resolvePendingFixups() { PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() + PendingFixup.Fixup.getOffset()); - // If the location symbol to relocate is in MCEncodedFragmentWithFixups, + // 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(); @@ -71,15 +71,9 @@ void MCObjectStreamer::resolvePendingFixups() { case MCFragment::FT_Relaxable: case MCFragment::FT_Dwarf: case MCFragment::FT_PseudoProbe: - cast>(SymFragment) - ->getFixups() - .push_back(PendingFixup.Fixup); - break; case MCFragment::FT_Data: case MCFragment::FT_CVDefRange: - cast>(SymFragment) - ->getFixups() - .push_back(PendingFixup.Fixup); + cast(SymFragment)->addFixup(PendingFixup.Fixup); break; default: PendingFixup.DF->addFixup(PendingFixup.Fixup); @@ -398,10 +392,9 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst, getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI); auto CodeOffset = DF->getContents().size(); - for (MCFixup &Fixup : Fixups) { + for (MCFixup &Fixup : Fixups) Fixup.setOffset(Fixup.getOffset() + CodeOffset); - DF->addFixup(Fixup); - } + DF->appendFixups(Fixups); DF->setHasInstructions(STI); DF->appendContents(Code); } @@ -414,8 +407,11 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, getContext().allocFragment(Inst, STI); insert(IF); - getAssembler().getEmitter().encodeInstruction(Inst, IF->getContents(), - IF->getFixups(), STI); + SmallVector Fixups; + getAssembler().getEmitter().encodeInstruction( + Inst, IF->getContentsForAppending(), Fixups, STI); + IF->doneAppending(); + IF->appendFixups(Fixups); } #ifndef NDEBUG diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index 9aad34e0d32ad..04e1cc5bcf41b 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -12,6 +12,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCFragment.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -37,10 +38,13 @@ MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) { bool MCSection::hasEnded() const { return End && End->isInSection(); } MCSection::~MCSection() { + // If ~MCRelaxableFragment becomes trivial (no longer store a MCInst member), + // this dtor can be made empty. for (auto &[_, Chain] : Subsections) { for (MCFragment *X = Chain.Head, *Y; X; X = Y) { Y = X->Next; - X->destroy(); + if (auto *F = dyn_cast(X)) + F->~MCRelaxableFragment(); } } } diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp index 9377a74b377ea..a43ca2eaf9f08 100644 --- a/llvm/lib/MC/MachObjectWriter.cpp +++ b/llvm/lib/MC/MachObjectWriter.cpp @@ -808,8 +808,8 @@ uint64_t MachObjectWriter::writeObject() { MCSection *CGProfileSection = getContext().getMachOSection( "__LLVM", "__cg_profile", 0, SectionKind::getMetadata()); auto &Frag = cast(*CGProfileSection->begin()); - Frag.getContents().clear(); - raw_svector_ostream OS(Frag.getContents()); + Frag.clearContents(); + raw_svector_ostream OS(Frag.getContentsForAppending()); for (const MCObjectWriter::CGProfileEntry &CGPE : CGProfile) { uint32_t FromIndex = CGPE.From->getSymbol().getIndex(); uint32_t ToIndex = CGPE.To->getSymbol().getIndex(); @@ -817,6 +817,7 @@ uint64_t MachObjectWriter::writeObject() { support::endian::write(OS, ToIndex, W.Endian); support::endian::write(OS, CGPE.Count, W.Endian); } + Frag.doneAppending(); } unsigned NumSections = Asm.end() - Asm.begin(); diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index 2ed0aa3d20fc9..b534aa63ed1b3 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -1071,7 +1071,7 @@ uint64_t WinCOFFWriter::writeObject() { auto *Sec = getContext().getCOFFSection(".llvm_addrsig", COFF::IMAGE_SCN_LNK_REMOVE); auto *Frag = cast(Sec->curFragList()->Head); - raw_svector_ostream OS(Frag->getContents()); + raw_svector_ostream OS(Frag->getContentsForAppending()); for (const MCSymbol *S : OWriter.AddrsigSyms) { if (!S->isRegistered()) continue; @@ -1086,6 +1086,7 @@ uint64_t WinCOFFWriter::writeObject() { "executePostLayoutBinding!"); encodeULEB128(SectionMap[TargetSection]->Symbol->getIndex(), OS); } + Frag->doneAppending(); } // Create the contents of the .llvm.call-graph-profile section. @@ -1093,7 +1094,7 @@ uint64_t WinCOFFWriter::writeObject() { auto *Sec = getContext().getCOFFSection(".llvm.call-graph-profile", COFF::IMAGE_SCN_LNK_REMOVE); auto *Frag = cast(Sec->curFragList()->Head); - raw_svector_ostream OS(Frag->getContents()); + raw_svector_ostream OS(Frag->getContentsForAppending()); for (const auto &CGPE : OWriter.getCGProfile()) { uint32_t FromIndex = CGPE.From->getSymbol().getIndex(); uint32_t ToIndex = CGPE.To->getSymbol().getIndex(); @@ -1101,6 +1102,7 @@ uint64_t WinCOFFWriter::writeObject() { support::endian::write(OS, ToIndex, W.Endian); support::endian::write(OS, CGPE.Count, W.Endian); } + Frag->doneAppending(); } assignFileOffsets(); diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp index f7bb33d2790a1..64192ed6632de 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -297,9 +297,8 @@ bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, int64_t LineDelta = DF.getLineDelta(); const MCExpr &AddrDelta = DF.getAddrDelta(); - SmallVectorImpl &Data = DF.getContents(); - SmallVectorImpl &Fixups = DF.getFixups(); - size_t OldSize = Data.size(); + SmallVector Fixups; + size_t OldSize = DF.getContents().size(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -308,8 +307,7 @@ bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, assert(IsAbsolute && "CFA with invalid expression"); (void)IsAbsolute; - Data.clear(); - Fixups.clear(); + SmallVector Data; raw_svector_ostream OS(Data); // INT64_MAX is a signal that this is actually a DW_LNE_end_sequence. @@ -354,6 +352,8 @@ bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, OS << uint8_t(dwarf::DW_LNS_copy); } + DF.setContents(Data); + DF.setFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; } @@ -361,9 +361,8 @@ bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, bool &WasRelaxed) const { const MCExpr &AddrDelta = DF.getAddrDelta(); - SmallVectorImpl &Data = DF.getContents(); - SmallVectorImpl &Fixups = DF.getFixups(); - size_t OldSize = Data.size(); + SmallVector Fixups; + size_t OldSize = DF.getContents().size(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -372,14 +371,12 @@ bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, assert(IsAbsolute && "CFA with invalid expression"); (void)IsAbsolute; - Data.clear(); - Fixups.clear(); - raw_svector_ostream OS(Data); - assert(getContext().getAsmInfo()->getMinInstAlignment() == 1 && "expected 1-byte alignment"); if (Value == 0) { - WasRelaxed = OldSize != Data.size(); + DF.clearContents(); + DF.clearFixups(); + WasRelaxed = OldSize != DF.getContents().size(); return true; } @@ -391,6 +388,8 @@ bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, Fixups.push_back(MCFixup::create(Offset, MBE.getRHS(), std::get<1>(FK))); }; + SmallVector Data; + raw_svector_ostream OS(Data); if (isUIntN(6, Value)) { OS << uint8_t(dwarf::DW_CFA_advance_loc); AddFixups(0, getRelocPairForSize(6)); @@ -409,6 +408,8 @@ bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, } else { llvm_unreachable("unsupported CFA encoding"); } + DF.setContents(Data); + DF.setFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index 8ed0aa8b832cf..24525ef3ab865 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -275,17 +275,16 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, int64_t LineDelta = DF.getLineDelta(); const MCExpr &AddrDelta = DF.getAddrDelta(); - SmallVectorImpl &Data = DF.getContents(); - SmallVectorImpl &Fixups = DF.getFixups(); - size_t OldSize = Data.size(); + SmallVector Fixups; + size_t OldSize = DF.getContents().size(); int64_t Value; [[maybe_unused]] bool IsAbsolute = AddrDelta.evaluateKnownAbsolute(Value, *Asm); assert(IsAbsolute && "CFA with invalid expression"); - Data.clear(); Fixups.clear(); + SmallVector Data; raw_svector_ostream OS(Data); // INT64_MAX is a signal that this is actually a DW_LNE_end_sequence. @@ -330,6 +329,8 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, OS << uint8_t(dwarf::DW_LNS_copy); } + DF.setContents(Data); + DF.setFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; } @@ -337,9 +338,8 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, bool &WasRelaxed) const { const MCExpr &AddrDelta = DF.getAddrDelta(); - SmallVectorImpl &Data = DF.getContents(); - SmallVectorImpl &Fixups = DF.getFixups(); - size_t OldSize = Data.size(); + SmallVector Fixups; + size_t OldSize = DF.getContents().size(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -348,14 +348,12 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, AddrDelta.evaluateKnownAbsolute(Value, *Asm); assert(IsAbsolute && "CFA with invalid expression"); - Data.clear(); - Fixups.clear(); - raw_svector_ostream OS(Data); - assert(getContext().getAsmInfo()->getMinInstAlignment() == 1 && "expected 1-byte alignment"); if (Value == 0) { - WasRelaxed = OldSize != Data.size(); + DF.clearContents(); + DF.clearFixups(); + WasRelaxed = OldSize != DF.getContents().size(); return true; } @@ -366,6 +364,8 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, Fixups.push_back(MCFixup::create(Offset, MBE.getRHS(), std::get<1>(Fixup))); }; + SmallVector Data; + raw_svector_ostream OS(Data); if (isUIntN(6, Value)) { OS << uint8_t(dwarf::DW_CFA_advance_loc); AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6}); @@ -384,6 +384,8 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, } else { llvm_unreachable("unsupported CFA encoding"); } + DF.setContents(Data); + DF.setFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 361d7b488d048..77e2011361162 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -847,7 +847,7 @@ bool X86AsmBackend::padInstructionViaRelaxation(MCRelaxableFragment &RF, return false; RF.setInst(Relaxed); RF.setContents(Code); - RF.getFixups() = Fixups; + RF.setFixups(Fixups); RemainingSize -= Delta; return true; }