[llvm] f5d49c7 - Revert "MCFragment: Use trailing data for fixed-size part" (#151383)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 30 13:48:56 PDT 2025
Author: Nikolay Panchenko
Date: 2025-07-30T16:48:53-04:00
New Revision: f5d49c71b49a99ea700c30208cff7039553a4403
URL: https://github.com/llvm/llvm-project/commit/f5d49c71b49a99ea700c30208cff7039553a4403
DIFF: https://github.com/llvm/llvm-project/commit/f5d49c71b49a99ea700c30208cff7039553a4403.diff
LOG: Revert "MCFragment: Use trailing data for fixed-size part" (#151383)
Reverts llvm/llvm-project#150846 due to unsigned underflow identifier by
UBSan in several tests
Added:
Modified:
llvm/include/llvm/MC/MCObjectStreamer.h
llvm/include/llvm/MC/MCSection.h
llvm/lib/MC/MCObjectStreamer.cpp
llvm/lib/MC/MCWin64EH.cpp
llvm/lib/MC/MCWinCOFFStreamer.cpp
llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
Removed:
llvm/test/MC/ELF/many-instructions.s
################################################################################
diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h
index 5ac7aba679ec4..4b43a8fadb925 100644
--- a/llvm/include/llvm/MC/MCObjectStreamer.h
+++ b/llvm/include/llvm/MC/MCObjectStreamer.h
@@ -52,10 +52,6 @@ class MCObjectStreamer : public MCStreamer {
DenseMap<const MCSymbol *, SmallVector<PendingAssignment, 1>>
pendingAssignments;
- SmallVector<std::unique_ptr<char[]>, 0> FragStorage;
- // Available bytes in the current block for trailing data or new fragments.
- size_t FragSpace = 0;
-
void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &);
void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
@@ -88,18 +84,11 @@ class MCObjectStreamer : public MCStreamer {
// Add a fragment with a variable-size tail and start a new empty fragment.
void insert(MCFragment *F);
- char *getCurFragEnd() const {
- return reinterpret_cast<char *>(CurFrag + 1) + CurFrag->getFixedSize();
- }
- MCFragment *allocFragSpace(size_t Headroom);
// Add a new fragment to the current section without a variable-size tail.
void newFragment();
- void ensureHeadroom(size_t Headroom);
void appendContents(ArrayRef<char> Contents);
void appendContents(size_t Num, char Elt);
- // Add a fixup to the current fragment. Call ensureHeadroom beforehand to
- // ensure the fixup and appended content apply to the same fragment.
void addFixup(const MCExpr *Value, MCFixupKind Kind);
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h
index 2e929d872e6fb..df8f617b610ad 100644
--- a/llvm/include/llvm/MC/MCSection.h
+++ b/llvm/include/llvm/MC/MCSection.h
@@ -93,7 +93,8 @@ class MCFragment {
// Track content and fixups for the fixed-size part as fragments are
// appended to the section. The content remains immutable, except when
// modified by applyFixup.
- uint32_t FixedSize = 0;
+ uint32_t ContentStart = 0;
+ uint32_t ContentEnd = 0;
uint32_t FixupStart = 0;
uint32_t FixupEnd = 0;
@@ -187,6 +188,18 @@ class MCFragment {
//== Content-related functions manage parent's storage using ContentStart and
// ContentSize.
+ // Get a SmallVector reference. The caller should call doneAppending to update
+ // `ContentEnd`.
+ SmallVectorImpl<char> &getContentsForAppending();
+ void doneAppending();
+ void appendContents(ArrayRef<char> Contents) {
+ getContentsForAppending().append(Contents.begin(), Contents.end());
+ doneAppending();
+ }
+ void appendContents(size_t Num, char Elt) {
+ getContentsForAppending().append(Num, Elt);
+ doneAppending();
+ }
MutableArrayRef<char> getContents();
ArrayRef<char> getContents() const;
@@ -195,10 +208,10 @@ class MCFragment {
MutableArrayRef<char> getVarContents();
ArrayRef<char> getVarContents() const;
- size_t getFixedSize() const { return FixedSize; }
+ size_t getFixedSize() const { return ContentEnd - ContentStart; }
size_t getVarSize() const { return VarContentEnd - VarContentStart; }
size_t getSize() const {
- return FixedSize + (VarContentEnd - VarContentStart);
+ return ContentEnd - ContentStart + (VarContentEnd - VarContentStart);
}
//== Fixup-related functions manage parent's storage using FixupStart and
@@ -621,11 +634,28 @@ class LLVM_ABI MCSection {
bool isBssSection() const { return IsBss; }
};
+inline SmallVectorImpl<char> &MCFragment::getContentsForAppending() {
+ SmallVectorImpl<char> &S = getParent()->ContentStorage;
+ if (LLVM_UNLIKELY(ContentEnd != S.size())) {
+ // Move the elements to the end. Reserve space to avoid invalidating
+ // S.begin()+I for `append`.
+ auto Size = ContentEnd - ContentStart;
+ auto I = std::exchange(ContentStart, S.size());
+ S.reserve(S.size() + Size);
+ S.append(S.begin() + I, S.begin() + I + Size);
+ }
+ return S;
+}
+inline void MCFragment::doneAppending() {
+ ContentEnd = getParent()->ContentStorage.size();
+}
inline MutableArrayRef<char> MCFragment::getContents() {
- return {reinterpret_cast<char *>(this + 1), FixedSize};
+ return MutableArrayRef(getParent()->ContentStorage)
+ .slice(ContentStart, ContentEnd - ContentStart);
}
inline ArrayRef<char> MCFragment::getContents() const {
- return {reinterpret_cast<const char *>(this + 1), FixedSize};
+ return ArrayRef(getParent()->ContentStorage)
+ .slice(ContentStart, ContentEnd - ContentStart);
}
inline MutableArrayRef<char> MCFragment::getVarContents() {
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index e82393a8477ea..e277143ac3899 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -46,83 +46,27 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
return nullptr;
}
-constexpr size_t FragBlockSize = 16384;
-// Ensure the new fragment can at least store a few bytes.
-constexpr size_t NewFragHeadroom = 8;
-
-static_assert(NewFragHeadroom >= alignof(MCFragment));
-static_assert(FragBlockSize >= sizeof(MCFragment) + NewFragHeadroom);
-
-MCFragment *MCObjectStreamer::allocFragSpace(size_t Headroom) {
- auto Size = std::max(FragBlockSize, sizeof(MCFragment) + Headroom);
- FragSpace = Size - sizeof(MCFragment);
- auto Chunk = std::unique_ptr<char[]>(new char[Size]);
- auto *F = reinterpret_cast<MCFragment *>(Chunk.get());
- FragStorage.push_back(std::move(Chunk));
- return F;
-}
-
void MCObjectStreamer::newFragment() {
- MCFragment *F;
- if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
- auto End = reinterpret_cast<size_t>(getCurFragEnd());
- F = reinterpret_cast<MCFragment *>(
- alignToPowerOf2(End, alignof(MCFragment)));
- FragSpace -= size_t(F) - End + sizeof(MCFragment);
- } else {
- F = allocFragSpace(0);
- }
- new (F) MCFragment();
- addFragment(F);
-}
-
-void MCObjectStreamer::ensureHeadroom(size_t Headroom) {
- if (Headroom <= FragSpace)
- return;
- auto *F = allocFragSpace(Headroom);
- new (F) MCFragment();
- addFragment(F);
+ addFragment(getContext().allocFragment<MCFragment>());
}
-void MCObjectStreamer::insert(MCFragment *Frag) {
- assert(Frag->getKind() != MCFragment::FT_Data &&
+void MCObjectStreamer::insert(MCFragment *F) {
+ assert(F->getKind() != MCFragment::FT_Data &&
"F should have a variable-size tail");
- // Frag is not connected to FragSpace. Before modifying CurFrag with
- // addFragment(Frag), allocate an empty fragment to maintain FragSpace
- // connectivity, potentially reusing CurFrag's associated space.
- MCFragment *F;
- if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
- auto End = reinterpret_cast<size_t>(getCurFragEnd());
- F = reinterpret_cast<MCFragment *>(
- alignToPowerOf2(End, alignof(MCFragment)));
- FragSpace -= size_t(F) - End + sizeof(MCFragment);
- } else {
- F = allocFragSpace(0);
- }
- new (F) MCFragment();
-
- addFragment(Frag);
addFragment(F);
+ newFragment();
}
void MCObjectStreamer::appendContents(ArrayRef<char> Contents) {
- ensureHeadroom(Contents.size());
- assert(FragSpace >= Contents.size());
- llvm::copy(Contents, getCurFragEnd());
- CurFrag->FixedSize += Contents.size();
- FragSpace -= Contents.size();
+ CurFrag->appendContents(Contents);
}
void MCObjectStreamer::appendContents(size_t Num, char Elt) {
- ensureHeadroom(Num);
- MutableArrayRef<char> Data(getCurFragEnd(), Num);
- llvm::fill(Data, Elt);
- CurFrag->FixedSize += Num;
- FragSpace -= Num;
+ CurFrag->appendContents(Num, Elt);
}
void MCObjectStreamer::addFixup(const MCExpr *Value, MCFixupKind Kind) {
- CurFrag->addFixup(MCFixup::create(getCurFragSize(), Value, Kind));
+ CurFrag->addFixup(MCFixup::create(CurFrag->getFixedSize(), Value, Kind));
}
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
@@ -171,8 +115,6 @@ void MCObjectStreamer::reset() {
}
EmitEHFrame = true;
EmitDebugFrame = false;
- FragStorage.clear();
- FragSpace = 0;
MCStreamer::reset();
}
@@ -201,6 +143,7 @@ void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc) {
MCStreamer::emitValueImpl(Value, Size, Loc);
+ MCFragment *DF = getCurrentFragment();
MCDwarfLineEntry::make(this, getCurrentSectionOnly());
@@ -215,9 +158,9 @@ void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
emitIntValue(AbsValue, Size);
return;
}
- ensureHeadroom(Size);
- addFixup(Value, MCFixup::getDataKindForSize(Size));
- appendContents(Size, 0);
+ DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
+ MCFixup::getDataKindForSize(Size)));
+ DF->appendContents(Size, 0);
}
MCSymbol *MCObjectStreamer::emitCFILabel() {
@@ -251,7 +194,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
// section.
MCFragment *F = CurFrag;
Symbol->setFragment(F);
- Symbol->setOffset(F->getFixedSize());
+ Symbol->setOffset(F->getContents().size());
emitPendingAssignments(Symbol);
}
@@ -317,21 +260,6 @@ void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
F0 = CurFrag;
}
- // To maintain connectivity between CurFrag and FragSpace when CurFrag is
- // modified, allocate an empty fragment and append it to the fragment list.
- // (Subsections[I].second.Tail is not connected to FragSpace.)
- MCFragment *F;
- if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
- auto End = reinterpret_cast<size_t>(getCurFragEnd());
- F = reinterpret_cast<MCFragment *>(
- alignToPowerOf2(End, alignof(MCFragment)));
- FragSpace -= size_t(F) - End + sizeof(MCFragment);
- } else {
- F = allocFragSpace(0);
- }
- new (F) MCFragment();
- F->setParent(Section);
-
auto &Subsections = Section->Subsections;
size_t I = 0, E = Subsections.size();
while (I != E && Subsections[I].first < Subsection)
@@ -339,16 +267,13 @@ void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
// 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<MCFragment>();
+ F->setParent(Section);
Subsections.insert(Subsections.begin() + I,
{Subsection, MCSection::FragList{F, F}});
- Section->CurFragList = &Subsections[I].second;
- CurFrag = F;
- } else {
- Section->CurFragList = &Subsections[I].second;
- CurFrag = Subsections[I].second.Tail;
- // Ensure CurFrag is associated with FragSpace.
- addFragment(F);
}
+ Section->CurFragList = &Subsections[I].second;
+ CurFrag = Section->CurFragList->Tail;
// Define the section symbol at subsection 0's initial fragment if required.
if (!NewSec)
@@ -419,15 +344,11 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
MCFragment *F = getCurrentFragment();
// Append the instruction to the data fragment.
- size_t CodeOffset = getCurFragSize();
- SmallString<16> Content;
+ size_t CodeOffset = F->getContents().size();
SmallVector<MCFixup, 1> Fixups;
- getAssembler().getEmitter().encodeInstruction(Inst, Content, Fixups, STI);
- appendContents(Content);
- if (CurFrag != F) {
- F = CurFrag;
- CodeOffset = 0;
- }
+ getAssembler().getEmitter().encodeInstruction(
+ Inst, F->getContentsForAppending(), Fixups, STI);
+ F->doneAppending();
F->setHasInstructions(STI);
if (Fixups.empty())
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index a87648afde7d6..72a8dd7031198 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -318,9 +318,6 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
// Emit the epilog instructions.
if (EnableUnwindV2) {
- // Ensure the fixups and appended content apply to the same fragment.
- OS->ensureHeadroom(info->EpilogMap.size() * 2);
-
bool IsLast = true;
for (const auto &Epilog : llvm::reverse(info->EpilogMap)) {
if (IsLast) {
diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp
index 8be5054ad25e2..1ffe25ccbc473 100644
--- a/llvm/lib/MC/MCWinCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp
@@ -280,7 +280,6 @@ void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {
void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) {
visitUsedSymbol(*Symbol);
const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
- ensureHeadroom(2);
addFixup(SRE, FK_SecRel_2);
appendContents(2, 0);
}
@@ -294,7 +293,6 @@ void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol,
if (Offset)
MCE = MCBinaryExpr::createAdd(
MCE, MCConstantExpr::create(Offset, getContext()), getContext());
- ensureHeadroom(4);
addFixup(MCE, FK_SecRel_4);
// Emit 4 bytes (zeros) to the object file.
appendContents(4, 0);
@@ -310,7 +308,6 @@ void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol,
if (Offset)
MCE = MCBinaryExpr::createAdd(
MCE, MCConstantExpr::create(Offset, getContext()), getContext());
- ensureHeadroom(4);
addFixup(MCE, FK_Data_4);
// Emit 4 bytes (zeros) to the object file.
appendContents(4, 0);
@@ -321,7 +318,6 @@ void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {
// Create Symbol for section number.
const MCExpr *MCE = MCCOFFSectionNumberTargetExpr::create(
*Symbol, this->getWriter(), getContext());
- ensureHeadroom(4);
addFixup(MCE, FK_Data_4);
// Emit 4 bytes (zeros) to the object file.
appendContents(4, 0);
@@ -332,7 +328,6 @@ void MCWinCOFFStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {
// Create Symbol for section offset.
const MCExpr *MCE =
MCCOFFSectionOffsetTargetExpr::create(*Symbol, getContext());
- ensureHeadroom(4);
addFixup(MCE, FK_Data_4);
// Emit 4 bytes (zeros) to the object file.
appendContents(4, 0);
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
index 7a8395a2e582b..d9680c7739a1b 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -1034,14 +1034,12 @@ MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
void MipsTargetELFStreamer::emitGPRel32Value(const MCExpr *Value) {
auto &S = getStreamer();
- S.ensureHeadroom(4);
S.addFixup(Value, Mips::fixup_Mips_GPREL32);
S.appendContents(4, 0);
}
void MipsTargetELFStreamer::emitGPRel64Value(const MCExpr *Value) {
auto &S = getStreamer();
- S.ensureHeadroom(8);
// fixup_Mips_GPREL32 desginates R_MIPS_GPREL32+R_MIPS_64 on MIPS64.
S.addFixup(Value, Mips::fixup_Mips_GPREL32);
S.appendContents(8, 0);
@@ -1049,28 +1047,24 @@ void MipsTargetELFStreamer::emitGPRel64Value(const MCExpr *Value) {
void MipsTargetELFStreamer::emitDTPRel32Value(const MCExpr *Value) {
auto &S = getStreamer();
- S.ensureHeadroom(4);
S.addFixup(Value, Mips::fixup_Mips_DTPREL32);
S.appendContents(4, 0);
}
void MipsTargetELFStreamer::emitDTPRel64Value(const MCExpr *Value) {
auto &S = getStreamer();
- S.ensureHeadroom(8);
S.addFixup(Value, Mips::fixup_Mips_DTPREL64);
S.appendContents(8, 0);
}
void MipsTargetELFStreamer::emitTPRel32Value(const MCExpr *Value) {
auto &S = getStreamer();
- S.ensureHeadroom(4);
S.addFixup(Value, Mips::fixup_Mips_TPREL32);
S.appendContents(4, 0);
}
void MipsTargetELFStreamer::emitTPRel64Value(const MCExpr *Value) {
auto &S = getStreamer();
- S.ensureHeadroom(8);
S.addFixup(Value, Mips::fixup_Mips_TPREL64);
S.appendContents(8, 0);
}
diff --git a/llvm/test/MC/ELF/many-instructions.s b/llvm/test/MC/ELF/many-instructions.s
deleted file mode 100644
index cbdb2a71680d4..0000000000000
--- a/llvm/test/MC/ELF/many-instructions.s
+++ /dev/null
@@ -1,10 +0,0 @@
-# REQUIRES: asserts
-# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o /dev/null -debug-only=mc-dump
-
-## Test that encodeInstruction may cause a new fragment to be created.
-# CHECK: 0 Data Size:16200
-# CHECK: 16200 Data Size:180
-
-.rept 16384/10
-movabsq $foo, %rax
-.endr
More information about the llvm-commits
mailing list