Skip to content

Revert "MCFragment: Use trailing data for fixed-size part" #151383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions llvm/include/llvm/MC/MCObjectStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
40 changes: 35 additions & 5 deletions llvm/include/llvm/MC/MCSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -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() {
Expand Down
119 changes: 20 additions & 99 deletions llvm/lib/MC/MCObjectStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -171,8 +115,6 @@ void MCObjectStreamer::reset() {
}
EmitEHFrame = true;
EmitDebugFrame = false;
FragStorage.clear();
FragSpace = 0;
MCStreamer::reset();
}

Expand Down Expand Up @@ -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());

Expand All @@ -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() {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -317,38 +260,20 @@ 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)
++I;
// 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)
Expand Down Expand Up @@ -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())
Expand Down
3 changes: 0 additions & 3 deletions llvm/lib/MC/MCWin64EH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 0 additions & 5 deletions llvm/lib/MC/MCWinCOFFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
6 changes: 0 additions & 6 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1034,43 +1034,37 @@ 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);
}

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);
}
Expand Down
Loading