MCStreamer: Add helpers and eliminate direct MCFragment operations

To facilitate optimizing the MCFragment internals, we don't want users
to access MCFragment directly.
This commit is contained in:
Fangrui Song 2025-07-20 21:57:57 -07:00
parent 6ebc42322c
commit 63b9cbd6e4
6 changed files with 43 additions and 64 deletions

View File

@ -83,10 +83,12 @@ public:
// Add a fragment with a variable-size tail and start a new empty fragment.
void insert(MCFragment *F);
void addFixup(const MCExpr *Value, MCFixupKind Kind, uint32_t Offset = 0);
// Add a new fragment to the current section without a variable-size tail.
void newFragment();
void appendContents(size_t Num, char Elt);
void addFixup(const MCExpr *Value, MCFixupKind Kind);
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
virtual void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment &F,
uint64_t Offset);

View File

@ -438,6 +438,7 @@ public:
assert(!CurFrag || CurFrag->getKind() == MCFragment::FT_Data);
return CurFrag;
}
size_t getCurFragOffset() const { return getCurrentFragment()->Offset; }
/// Save the current and previous section on the section stack.
void pushSection() {
SectionStack.push_back(

View File

@ -58,10 +58,12 @@ void MCObjectStreamer::insert(MCFragment *F) {
newFragment();
}
void MCObjectStreamer::addFixup(const MCExpr *Value, MCFixupKind Kind,
uint32_t Offset) {
CurFrag->addFixup(
MCFixup::create(CurFrag->getFixedSize() + Offset, Value, Kind));
void MCObjectStreamer::appendContents(size_t Num, char Elt) {
CurFrag->appendContents(Num, Elt);
}
void MCObjectStreamer::addFixup(const MCExpr *Value, MCFixupKind Kind) {
CurFrag->addFixup(MCFixup::create(CurFrag->getFixedSize(), Value, Kind));
}
// As a compile-time optimization, avoid allocating and evaluating an MCExpr

View File

@ -318,15 +318,13 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
// Emit the epilog instructions.
if (EnableUnwindV2) {
MCFragment *DF = OS->getCurrentFragment();
bool IsLast = true;
for (const auto &Epilog : llvm::reverse(info->EpilogMap)) {
if (IsLast) {
IsLast = false;
uint8_t Flags = LastEpilogIsAtEnd ? 0x01 : 0;
streamer.emitInt8(EpilogSize);
streamer.emitInt8((Flags << 4) | Win64EH::UOP_Epilog);
OS->emitInt8(EpilogSize);
OS->emitInt8((Flags << 4) | Win64EH::UOP_Epilog);
if (LastEpilogIsAtEnd)
continue;
@ -337,9 +335,8 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
// layout has been completed.
auto *MCE = MCUnwindV2EpilogTargetExpr::create(*info, Epilog.second,
EpilogSize, context);
MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_2);
DF->addFixup(Fixup);
DF->appendContents(2, 0);
OS->addFixup(MCE, FK_Data_2);
OS->appendContents(2, 0);
}
}
if (AddPaddingEpilogCode)

View File

@ -278,35 +278,28 @@ void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {
void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) {
visitUsedSymbol(*Symbol);
MCFragment *DF = getCurrentFragment();
const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2);
DF->addFixup(Fixup);
DF->appendContents(2, 0);
addFixup(SRE, FK_SecRel_2);
appendContents(2, 0);
}
void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol,
uint64_t Offset) {
visitUsedSymbol(*Symbol);
MCFragment *DF = getCurrentFragment();
// Create Symbol A for the relocation relative reference.
const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
// Add the constant offset, if given.
if (Offset)
MCE = MCBinaryExpr::createAdd(
MCE, MCConstantExpr::create(Offset, getContext()), getContext());
// Build the secrel32 relocation.
MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
// Record the relocation.
DF->addFixup(Fixup);
addFixup(MCE, FK_SecRel_4);
// Emit 4 bytes (zeros) to the object file.
DF->appendContents(4, 0);
appendContents(4, 0);
}
void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol,
int64_t Offset) {
visitUsedSymbol(*Symbol);
MCFragment *DF = getCurrentFragment();
// Create Symbol A for the relocation relative reference.
const MCExpr *MCE = MCSymbolRefExpr::create(
Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
@ -314,40 +307,29 @@ void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol,
if (Offset)
MCE = MCBinaryExpr::createAdd(
MCE, MCConstantExpr::create(Offset, getContext()), getContext());
// Build the imgrel relocation.
MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
// Record the relocation.
DF->addFixup(Fixup);
addFixup(MCE, FK_Data_4);
// Emit 4 bytes (zeros) to the object file.
DF->appendContents(4, 0);
appendContents(4, 0);
}
void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {
visitUsedSymbol(*Symbol);
MCFragment *DF = getCurrentFragment();
// Create Symbol for section number.
const MCExpr *MCE = MCCOFFSectionNumberTargetExpr::create(
*Symbol, this->getWriter(), getContext());
// Build the relocation.
MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
// Record the relocation.
DF->addFixup(Fixup);
addFixup(MCE, FK_Data_4);
// Emit 4 bytes (zeros) to the object file.
DF->appendContents(4, 0);
appendContents(4, 0);
}
void MCWinCOFFStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {
visitUsedSymbol(*Symbol);
MCFragment *DF = getCurrentFragment();
// Create Symbol for section offset.
const MCExpr *MCE =
MCCOFFSectionOffsetTargetExpr::create(*Symbol, getContext());
// Build the relocation.
MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
// Record the relocation.
DF->addFixup(Fixup);
addFixup(MCE, FK_Data_4);
// Emit 4 bytes (zeros) to the object file.
DF->appendContents(4, 0);
appendContents(4, 0);
}
void MCWinCOFFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,

View File

@ -1033,45 +1033,40 @@ MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
}
void MipsTargetELFStreamer::emitGPRel32Value(const MCExpr *Value) {
MCFragment *DF = getStreamer().getCurrentFragment();
DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
Mips::fixup_Mips_GPREL32));
DF->appendContents(4, 0);
auto &S = getStreamer();
S.addFixup(Value, Mips::fixup_Mips_GPREL32);
S.appendContents(4, 0);
}
void MipsTargetELFStreamer::emitGPRel64Value(const MCExpr *Value) {
MCFragment *DF = getStreamer().getCurrentFragment();
DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
Mips::fixup_Mips_GPREL32));
DF->appendContents(8, 0);
auto &S = getStreamer();
// 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) {
MCFragment *DF = getStreamer().getCurrentFragment();
DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
Mips::fixup_Mips_DTPREL32));
DF->appendContents(4, 0);
auto &S = getStreamer();
S.addFixup(Value, Mips::fixup_Mips_DTPREL32);
S.appendContents(4, 0);
}
void MipsTargetELFStreamer::emitDTPRel64Value(const MCExpr *Value) {
MCFragment *DF = getStreamer().getCurrentFragment();
DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
Mips::fixup_Mips_DTPREL64));
DF->appendContents(8, 0);
auto &S = getStreamer();
S.addFixup(Value, Mips::fixup_Mips_DTPREL64);
S.appendContents(8, 0);
}
void MipsTargetELFStreamer::emitTPRel32Value(const MCExpr *Value) {
MCFragment *DF = getStreamer().getCurrentFragment();
DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
Mips::fixup_Mips_TPREL32));
DF->appendContents(4, 0);
auto &S = getStreamer();
S.addFixup(Value, Mips::fixup_Mips_TPREL32);
S.appendContents(4, 0);
}
void MipsTargetELFStreamer::emitTPRel64Value(const MCExpr *Value) {
MCFragment *DF = getStreamer().getCurrentFragment();
DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
Mips::fixup_Mips_TPREL64));
DF->appendContents(8, 0);
auto &S = getStreamer();
S.addFixup(Value, Mips::fixup_Mips_TPREL64);
S.appendContents(8, 0);
}
void MipsTargetELFStreamer::emitDirectiveSetMicroMips() {