aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp21
-rw-r--r--llvm/lib/MC/MCAssembler.cpp219
-rw-r--r--llvm/lib/MC/MCCodeView.cpp17
-rw-r--r--llvm/lib/MC/MCDwarf.cpp11
-rw-r--r--llvm/lib/MC/MCELFStreamer.cpp2
-rw-r--r--llvm/lib/MC/MCExpr.cpp9
-rw-r--r--llvm/lib/MC/MCFragment.cpp24
-rw-r--r--llvm/lib/MC/MCMachOStreamer.cpp13
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp98
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp16
-rw-r--r--llvm/lib/MC/MCParser/MCTargetAsmParser.cpp7
-rw-r--r--llvm/lib/MC/MCSection.cpp28
-rw-r--r--llvm/lib/MC/MCSectionCOFF.cpp4
-rw-r--r--llvm/lib/MC/MCSectionELF.cpp2
-rw-r--r--llvm/lib/MC/MCStreamer.cpp8
-rw-r--r--llvm/lib/MC/MCTargetOptionsCommandFlags.cpp7
-rw-r--r--llvm/lib/MC/MCWin64EH.cpp11
-rw-r--r--llvm/lib/MC/MCWinCOFFStreamer.cpp40
-rw-r--r--llvm/lib/MC/MCXCOFFStreamer.cpp2
-rw-r--r--llvm/lib/MC/MachObjectWriter.cpp23
-rw-r--r--llvm/lib/MC/WasmObjectWriter.cpp44
-rw-r--r--llvm/lib/MC/WinCOFFObjectWriter.cpp31
22 files changed, 292 insertions, 345 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 67c53e0..7119ef4 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -345,7 +345,7 @@ public:
void emitIdent(StringRef IdentString) override;
void emitCFIBKeyFrame() override;
void emitCFIMTETaggedFrame() override;
- void emitCFISections(bool EH, bool Debug) override;
+ void emitCFISections(bool EH, bool Debug, bool SFrame) override;
void emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) override;
void emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) override;
void emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) override;
@@ -1906,15 +1906,24 @@ void MCAsmStreamer::emitIdent(StringRef IdentString) {
EmitEOL();
}
-void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
- MCStreamer::emitCFISections(EH, Debug);
+void MCAsmStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
+ MCStreamer::emitCFISections(EH, Debug, SFrame);
OS << "\t.cfi_sections ";
+ bool C = false;
if (EH) {
OS << ".eh_frame";
- if (Debug)
- OS << ", .debug_frame";
- } else if (Debug) {
+ C = true;
+ }
+ if (Debug) {
+ if (C)
+ OS << ", ";
OS << ".debug_frame";
+ C = true;
+ }
+ if (SFrame) {
+ if (C)
+ OS << ", ";
+ OS << ".sframe";
}
EmitEOL();
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index 9420924..2b56e2a 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -196,6 +196,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
switch (F.getKind()) {
case MCFragment::FT_Data:
case MCFragment::FT_Relaxable:
+ case MCFragment::FT_Align:
case MCFragment::FT_LEB:
case MCFragment::FT_Dwarf:
case MCFragment::FT_DwarfFrame:
@@ -226,28 +227,6 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
case MCFragment::FT_SymbolId:
return 4;
- case MCFragment::FT_Align: {
- const MCAlignFragment &AF = cast<MCAlignFragment>(F);
- unsigned Offset = getFragmentOffset(AF);
- unsigned Size = offsetToAlignment(Offset, AF.getAlignment());
-
- // Insert extra Nops for code alignment if the target define
- // shouldInsertExtraNopBytesForCodeAlign target hook.
- if (AF.getParent()->useCodeAlign() && AF.hasEmitNops() &&
- getBackend().shouldInsertExtraNopBytesForCodeAlign(AF, Size))
- return Size;
-
- // If we are padding with nops, force the padding to be larger than the
- // minimum nop size.
- if (Size > 0 && AF.hasEmitNops()) {
- while (Size % getBackend().getMinimumNopSize())
- Size += AF.getAlignment().value();
- }
- if (Size > AF.getMaxBytesToEmit())
- return 0;
- return Size;
- }
-
case MCFragment::FT_Org: {
const MCOrgFragment &OF = cast<MCOrgFragment>(F);
MCValue Value;
@@ -383,7 +362,7 @@ uint64_t MCAssembler::getSectionAddressSize(const MCSection &Sec) const {
uint64_t MCAssembler::getSectionFileSize(const MCSection &Sec) const {
// Virtual sections have no file size.
- if (Sec.isVirtualSection())
+ if (Sec.isBssSection())
return 0;
return getSectionAddressSize(Sec);
}
@@ -431,48 +410,45 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
const auto &EF = cast<MCFragment>(F);
OS << StringRef(EF.getContents().data(), EF.getContents().size());
OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size());
- break;
- }
+ } break;
+
case MCFragment::FT_Align: {
++stats::EmittedAlignFragments;
- const MCAlignFragment &AF = cast<MCAlignFragment>(F);
- assert(AF.getFillLen() && "Invalid virtual align in concrete fragment!");
+ OS << StringRef(F.getContents().data(), F.getContents().size());
+ assert(F.getAlignFillLen() &&
+ "Invalid virtual align in concrete fragment!");
- uint64_t Count = FragmentSize / AF.getFillLen();
- assert(FragmentSize % AF.getFillLen() == 0 &&
+ uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen();
+ assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 &&
"computeFragmentSize computed size is incorrect");
- // See if we are aligning with nops, and if so do that first to try to fill
- // the Count bytes. Then if that did not fill any bytes or there are any
- // bytes left to fill use the Value and ValueSize to fill the rest.
- // If we are aligning with nops, ask that target to emit the right data.
- if (AF.hasEmitNops()) {
- if (!Asm.getBackend().writeNopData(OS, Count, AF.getSubtargetInfo()))
- report_fatal_error("unable to write nop sequence of " +
- Twine(Count) + " bytes");
- break;
- }
-
- // Otherwise, write out in multiples of the value size.
- for (uint64_t i = 0; i != Count; ++i) {
- switch (AF.getFillLen()) {
- default: llvm_unreachable("Invalid size!");
- case 1:
- OS << char(AF.getFill());
- break;
- case 2:
- support::endian::write<uint16_t>(OS, AF.getFill(), Endian);
- break;
- case 4:
- support::endian::write<uint32_t>(OS, AF.getFill(), Endian);
- break;
- case 8:
- support::endian::write<uint64_t>(OS, AF.getFill(), Endian);
- break;
+ // In the nops mode, call the backend hook to write `Count` nops.
+ if (F.hasAlignEmitNops()) {
+ if (!Asm.getBackend().writeNopData(OS, Count, F.getSubtargetInfo()))
+ reportFatalInternalError("unable to write nop sequence of " +
+ Twine(Count) + " bytes");
+ } else {
+ // Otherwise, write out in multiples of the value size.
+ for (uint64_t i = 0; i != Count; ++i) {
+ switch (F.getAlignFillLen()) {
+ default:
+ llvm_unreachable("Invalid size!");
+ case 1:
+ OS << char(F.getAlignFill());
+ break;
+ case 2:
+ support::endian::write<uint16_t>(OS, F.getAlignFill(), Endian);
+ break;
+ case 4:
+ support::endian::write<uint32_t>(OS, F.getAlignFill(), Endian);
+ break;
+ case 8:
+ support::endian::write<uint64_t>(OS, F.getAlignFill(), Endian);
+ break;
+ }
}
}
- break;
- }
+ } break;
case MCFragment::FT_Fill: {
++stats::EmittedFillFragments;
@@ -583,42 +559,45 @@ void MCAssembler::writeSectionData(raw_ostream &OS,
const MCSection *Sec) const {
assert(getBackendPtr() && "Expected assembler backend");
- // Ignore virtual sections.
- if (Sec->isVirtualSection()) {
+ if (Sec->isBssSection()) {
assert(getSectionFileSize(*Sec) == 0 && "Invalid size for section!");
- // Check that contents are only things legal inside a virtual section.
+ // Ensure no fixups or non-zero bytes are written to BSS sections, catching
+ // errors in both input assembly code and MCStreamer API usage. Location is
+ // not tracked for efficiency.
+ auto Fn = [](char c) { return c != 0; };
for (const MCFragment &F : *Sec) {
+ bool HasNonZero = false;
switch (F.getKind()) {
- default: llvm_unreachable("Invalid fragment in virtual section!");
- case MCFragment::FT_Data: {
- // Check that we aren't trying to write a non-zero contents (or fixups)
- // into a virtual section. This is to support clients which use standard
- // directives to fill the contents of virtual sections.
- if (F.getFixups().size() || F.getVarFixups().size())
- reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" +
- Sec->getName() + "' cannot have fixups");
- for (char C : F.getContents())
- if (C) {
- reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" +
- Sec->getName() +
- "' cannot have non-zero initializers");
- break;
- }
+ default:
+ reportFatalInternalError("BSS section '" + Sec->getName() +
+ "' contains invalid fragment");
+ break;
+ case MCFragment::FT_Data:
+ case MCFragment::FT_Relaxable:
+ HasNonZero =
+ any_of(F.getContents(), Fn) || any_of(F.getVarContents(), Fn);
break;
- }
case MCFragment::FT_Align:
- // Check that we aren't trying to write a non-zero value into a virtual
- // section.
- assert((cast<MCAlignFragment>(F).getFillLen() == 0 ||
- cast<MCAlignFragment>(F).getFill() == 0) &&
- "Invalid align in virtual section!");
+ // Disallowed for API usage. AsmParser changes non-zero fill values to
+ // 0.
+ assert(F.getAlignFill() == 0 && "Invalid align in virtual section!");
break;
case MCFragment::FT_Fill:
- assert((cast<MCFillFragment>(F).getValue() == 0) &&
- "Invalid fill in virtual section!");
+ HasNonZero = cast<MCFillFragment>(F).getValue() != 0;
break;
case MCFragment::FT_Org:
+ HasNonZero = cast<MCOrgFragment>(F).getValue() != 0;
+ break;
+ }
+ if (HasNonZero) {
+ reportError(SMLoc(), "BSS section '" + Sec->getName() +
+ "' cannot have non-zero bytes");
+ break;
+ }
+ if (F.getFixups().size() || F.getVarFixups().size()) {
+ reportError(SMLoc(),
+ "BSS section '" + Sec->getName() + "' cannot have fixups");
break;
}
}
@@ -722,34 +701,25 @@ void MCAssembler::layout() {
for (MCSection &Sec : *this) {
for (MCFragment &F : Sec) {
// Process fragments with fixups here.
- if (F.isEncoded()) {
- auto Contents = F.getContents();
- for (MCFixup &Fixup : F.getFixups()) {
+ auto Contents = F.getContents();
+ for (MCFixup &Fixup : F.getFixups()) {
+ uint64_t FixedValue;
+ MCValue Target;
+ evaluateFixup(F, Fixup, Target, FixedValue,
+ /*RecordReloc=*/true, Contents);
+ }
+ if (F.getVarFixups().size()) {
+ // In the variable part, fixup offsets are relative to the fixed part's
+ // start. Extend the variable contents to the left to account for the
+ // fixed part size.
+ Contents = MutableArrayRef(F.getParent()->ContentStorage)
+ .slice(F.VarContentStart - Contents.size(), F.getSize());
+ for (MCFixup &Fixup : F.getVarFixups()) {
uint64_t FixedValue;
MCValue Target;
evaluateFixup(F, Fixup, Target, FixedValue,
/*RecordReloc=*/true, Contents);
}
- // In the variable part, fixup offsets are relative to the fixed part's
- // start. Extend the variable contents to the left to account for the
- // fixed part size.
- auto VarFixups = F.getVarFixups();
- if (VarFixups.size()) {
- Contents =
- MutableArrayRef(F.getParent()->ContentStorage)
- .slice(F.VarContentStart - Contents.size(), F.getSize());
- for (MCFixup &Fixup : VarFixups) {
- uint64_t FixedValue;
- MCValue Target;
- evaluateFixup(F, Fixup, Target, FixedValue,
- /*RecordReloc=*/true, Contents);
- }
- }
- } else if (auto *AF = dyn_cast<MCAlignFragment>(&F)) {
- // For RISC-V linker relaxation, an alignment relocation might be
- // needed.
- if (AF->hasEmitNops())
- getBackend().shouldInsertFixupForCodeAlign(*this, *AF);
}
}
}
@@ -953,15 +923,15 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCFragment &F) {
}
bool MCAssembler::relaxCVInlineLineTable(MCCVInlineLineTableFragment &F) {
- unsigned OldSize = F.getContents().size();
+ unsigned OldSize = F.getVarContents().size();
getContext().getCVContext().encodeInlineLineTable(*this, F);
- return OldSize != F.getContents().size();
+ return OldSize != F.getVarContents().size();
}
bool MCAssembler::relaxCVDefRange(MCCVDefRangeFragment &F) {
- unsigned OldSize = F.getContents().size();
+ unsigned OldSize = F.getVarContents().size();
getContext().getCVContext().encodeDefRange(*this, F);
- return OldSize != F.getContents().size();
+ return OldSize != F.getVarContents().size();
}
bool MCAssembler::relaxFill(MCFillFragment &F) {
@@ -1000,7 +970,32 @@ void MCAssembler::layoutSection(MCSection &Sec) {
uint64_t Offset = 0;
for (MCFragment &F : Sec) {
F.Offset = Offset;
- Offset += computeFragmentSize(F);
+ if (F.getKind() == MCFragment::FT_Align) {
+ Offset += F.getFixedSize();
+ unsigned Size = offsetToAlignment(Offset, F.getAlignment());
+ // In the nops mode, RISC-V style linker relaxation might adjust the size
+ // and add a fixup, even if `Size` is originally 0.
+ bool AlignFixup = false;
+ if (F.hasAlignEmitNops()) {
+ AlignFixup = getBackend().relaxAlign(F, Size);
+ // If the backend does not handle the fragment specially, pad with nops,
+ // but ensure that the padding is larger than the minimum nop size.
+ if (!AlignFixup)
+ while (Size % getBackend().getMinimumNopSize())
+ Size += F.getAlignment().value();
+ }
+ if (!AlignFixup && Size > F.getAlignMaxBytesToEmit())
+ Size = 0;
+ // Update the variable tail size, offset by FixedSize to prevent ubsan
+ // pointer-overflow in evaluateFixup. The content is ignored.
+ F.VarContentStart = F.getFixedSize();
+ F.VarContentEnd = F.VarContentStart + Size;
+ if (F.VarContentEnd > F.getParent()->ContentStorage.size())
+ F.getParent()->ContentStorage.resize(F.VarContentEnd);
+ Offset += Size;
+ } else {
+ Offset += computeFragmentSize(F);
+ }
}
}
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp
index 1f98251..7d528a5 100644
--- a/llvm/lib/MC/MCCodeView.cpp
+++ b/llvm/lib/MC/MCCodeView.cpp
@@ -26,8 +26,10 @@ using namespace llvm;
using namespace llvm::codeview;
void CodeViewContext::finish() {
- if (StrTabFragment)
- StrTabFragment->setContents(StrTab);
+ if (!StrTabFragment)
+ return;
+ assert(StrTabFragment->getKind() == MCFragment::FT_Data);
+ StrTabFragment->setVarContents(StrTab);
}
/// This is a valid number for use with .cv_loc if we've already seen a .cv_file
@@ -166,8 +168,9 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
// somewhere else. If somebody wants two string tables in their .s file, one
// will just be empty.
if (!StrTabFragment) {
- StrTabFragment = Ctx.allocFragment<MCFragment>();
- OS.insert(StrTabFragment);
+ OS.newFragment();
+ StrTabFragment = OS.getCurrentFragment();
+ OS.newFragment();
}
OS.emitValueToAlignment(Align(4), 0);
@@ -603,7 +606,7 @@ void CodeViewContext::encodeInlineLineTable(const MCAssembler &Asm,
compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer);
- Frag.setContents(Buffer);
+ Frag.setVarContents(Buffer);
}
void CodeViewContext::encodeDefRange(const MCAssembler &Asm,
@@ -691,6 +694,6 @@ void CodeViewContext::encodeDefRange(const MCAssembler &Asm,
}
}
- Frag.setContents(Contents);
- Frag.setFixups(Fixups);
+ Frag.setVarContents(Contents);
+ Frag.setVarFixups(Fixups);
}
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index b1dced7..e7c0d37 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -447,10 +447,17 @@ static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));
}
if (HasAnySource) {
+ // From https://dwarfstd.org/issues/180201.1.html
+ // * The value is an empty null-terminated string if no source is available
+ StringRef Source = DwarfFile.Source.value_or(StringRef());
+ // * If the source is available but is an empty file then the value is a
+ // null-terminated single "\n".
+ if (DwarfFile.Source && DwarfFile.Source->empty())
+ Source = "\n";
if (LineStr)
- LineStr->emitRef(MCOS, DwarfFile.Source.value_or(StringRef()));
+ LineStr->emitRef(MCOS, Source);
else {
- MCOS->emitBytes(DwarfFile.Source.value_or(StringRef())); // Source and...
+ MCOS->emitBytes(Source); // Source and...
MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
}
}
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 49071bd..b8cbaea5 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -88,7 +88,7 @@ void MCELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
if (SectionELF->getFlags() & ELF::SHF_GNU_RETAIN)
getWriter().markGnuAbi();
- changeSectionImpl(Section, Subsection);
+ MCObjectStreamer::changeSection(Section, Subsection);
Asm.registerSymbol(*Section->getBeginSymbol());
}
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 22dff49..dbb2fd1 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -370,7 +370,6 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
}
int64_t Num;
- unsigned Count;
if (DF) {
Displacement += DF->getContents().size();
} else if (F->getKind() == MCFragment::FT_Relaxable &&
@@ -379,11 +378,9 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
// After layout, during relocation generation, it can be treated as a
// data fragment.
Displacement += F->getSize();
- } else if (auto *AF = dyn_cast<MCAlignFragment>(F);
- AF && Layout && AF->hasEmitNops() &&
- !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign(
- *AF, Count)) {
- Displacement += Asm->computeFragmentSize(*AF);
+ } else if (F->getKind() == MCFragment::FT_Align && Layout &&
+ F->isLinkerRelaxable()) {
+ Displacement += Asm->computeFragmentSize(*F);
} else if (auto *FF = dyn_cast<MCFillFragment>(F);
FF && FF->getNumValues().evaluateAsAbsolute(Num)) {
Displacement += Num * FF->getValueSize();
diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp
index fe7afd4..3c395e5 100644
--- a/llvm/lib/MC/MCFragment.cpp
+++ b/llvm/lib/MC/MCFragment.cpp
@@ -72,17 +72,9 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
};
switch (getKind()) {
- case MCFragment::FT_Align: {
- const auto *AF = cast<MCAlignFragment>(this);
- OS << " Align:" << AF->getAlignment().value() << " Fill:" << AF->getFill()
- << " FillLen:" << unsigned(AF->getFillLen())
- << " MaxBytesToEmit:" << AF->getMaxBytesToEmit();
- if (AF->hasEmitNops())
- OS << " Nops";
- break;
- }
case MCFragment::FT_Data:
case MCFragment::FT_Relaxable:
+ case MCFragment::FT_Align:
case MCFragment::FT_LEB:
case MCFragment::FT_Dwarf:
case MCFragment::FT_DwarfFrame: {
@@ -91,8 +83,13 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
auto Fixed = getContents();
auto Var = getVarContents();
OS << " Size:" << Fixed.size();
- if (getKind() != MCFragment::FT_Data)
+ if (getKind() != MCFragment::FT_Data) {
OS << '+' << Var.size();
+ // FT_Align uses getVarContents to track the size, but the content is
+ // ignored and not useful.
+ if (getKind() == MCFragment::FT_Align)
+ Var = {};
+ }
OS << " [";
for (unsigned i = 0, e = Fixed.size(); i != e; ++i) {
if (i) OS << ",";
@@ -111,6 +108,13 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
OS << ' ';
getInst().dump_pretty(OS);
break;
+ case MCFragment::FT_Align:
+ OS << "\n Align:" << getAlignment().value() << " Fill:" << getAlignFill()
+ << " FillLen:" << unsigned(getAlignFillLen())
+ << " MaxBytesToEmit:" << getAlignMaxBytesToEmit();
+ if (hasAlignEmitNops())
+ OS << " Nops";
+ break;
case MCFragment::FT_LEB: {
OS << " Value:";
getLEBValue().print(OS, nullptr);
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 43598ef..8f023bd 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -132,8 +132,7 @@ public:
} // end anonymous namespace.
void MCMachOStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
- // Change the section normally.
- changeSectionImpl(Section, Subsection);
+ MCObjectStreamer::changeSection(Section, Subsection);
// Output a linker-local symbol so we don't need section-relative local
// relocations. The linker hates us when we do that.
@@ -161,7 +160,7 @@ void MCMachOStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
// We have to create a new fragment if this is an atom defining symbol,
// fragments cannot span atoms.
if (cast<MCSymbolMachO>(Symbol)->isSymbolLinkerVisible())
- insert(getContext().allocFragment<MCFragment>());
+ newFragment();
MCObjectStreamer::emitLabel(Symbol, Loc);
@@ -393,7 +392,7 @@ void MCMachOStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
// On darwin all virtual sections have zerofill type. Disallow the usage of
// .zerofill in non-virtual functions. If something similar is needed, use
// .space or .zero.
- if (!Section->isVirtualSection()) {
+ if (!Section->isBssSection()) {
getContext().reportError(
Loc, "The usage of .zerofill is restricted to sections of "
"ZEROFILL type. Use .zero or .space instead.");
@@ -479,7 +478,8 @@ void MCMachOStreamer::finalizeCGProfile() {
// and set its size now so that it's accounted for in layout.
MCSection *CGProfileSection = Asm.getContext().getMachOSection(
"__LLVM", "__cg_profile", 0, SectionKind::getMetadata());
- changeSection(CGProfileSection);
+ // Call the base class changeSection to omit the linker-local label.
+ MCObjectStreamer::changeSection(CGProfileSection);
// For each entry, reserve space for 2 32-bit indices and a 64-bit count.
size_t SectionBytes =
W.getCGProfile().size() * (2 * sizeof(uint32_t) + sizeof(uint64_t));
@@ -511,7 +511,8 @@ void MCMachOStreamer::createAddrSigSection() {
// to be computed immediately after in order for it to be exported correctly.
MCSection *AddrSigSection =
Asm.getContext().getObjectFileInfo()->getAddrSigSection();
- changeSection(AddrSigSection);
+ // Call the base class changeSection to omit the linker-local label.
+ MCObjectStreamer::changeSection(AddrSigSection);
auto *Frag = cast<MCFragment>(AddrSigSection->curFragList()->Head);
// We will generate a series of pointer-sized symbol relocations at offset
// 0x0. Set the section size to be large enough to contain a single pointer
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index f61dda6..d7f4be1 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -33,6 +33,7 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context,
Context, std::move(TAB), std::move(Emitter), std::move(OW))),
EmitEHFrame(true), EmitDebugFrame(false) {
assert(Assembler->getBackendPtr() && Assembler->getEmitterPtr());
+ IsObj = true;
setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
if (Context.getTargetOptions() && Context.getTargetOptions()->MCRelaxAll)
Assembler->setRelaxAll(true);
@@ -46,6 +47,25 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
return nullptr;
}
+void MCObjectStreamer::newFragment() {
+ addFragment(getContext().allocFragment<MCFragment>());
+}
+
+void MCObjectStreamer::insert(MCFragment *F) {
+ assert(F->getKind() != MCFragment::FT_Data &&
+ "F should have a variable-size tail");
+ addFragment(F);
+ newFragment();
+}
+
+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
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed
// part.
@@ -106,32 +126,21 @@ void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) {
MCDwarfFrameEmitter::Emit(*this, MAB, false);
}
-MCFragment *MCObjectStreamer::getOrCreateDataFragment() {
- // TODO: Start a new fragment whenever finalizing the variable-size tail of a
- // previous one, so that all getOrCreateDataFragment calls can be replaced
- // with getCurrentFragment
- auto *F = getCurrentFragment();
- if (F->getKind() != MCFragment::FT_Data) {
- F = getContext().allocFragment<MCFragment>();
- insert(F);
- }
- return F;
-}
-
void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
Assembler->registerSymbol(Sym);
}
-void MCObjectStreamer::emitCFISections(bool EH, bool Debug) {
- MCStreamer::emitCFISections(EH, Debug);
+void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
+ MCStreamer::emitCFISections(EH, Debug, SFrame);
EmitEHFrame = EH;
EmitDebugFrame = Debug;
+ EmitSFrame = SFrame;
}
void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc) {
MCStreamer::emitValueImpl(Value, Size, Loc);
- MCFragment *DF = getOrCreateDataFragment();
+ MCFragment *DF = getCurrentFragment();
MCDwarfLineEntry::make(this, getCurrentSectionOnly());
@@ -180,7 +189,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
// If there is a current fragment, mark the symbol as pointing into it.
// Otherwise queue the label and set its fragment pointer when we emit the
// next fragment.
- MCFragment *F = getOrCreateDataFragment();
+ MCFragment *F = getCurrentFragment();
Symbol->setFragment(F);
Symbol->setOffset(F->getContents().size());
@@ -214,7 +223,7 @@ void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {
emitULEB128IntValue(IntValue);
return;
}
- auto *F = getOrCreateDataFragment();
+ auto *F = getCurrentFragment();
F->makeLEB(false, Value);
newFragment();
}
@@ -225,7 +234,7 @@ void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {
emitSLEB128IntValue(IntValue);
return;
}
- auto *F = getOrCreateDataFragment();
+ auto *F = getCurrentFragment();
F->makeLEB(true, Value);
newFragment();
}
@@ -236,11 +245,6 @@ void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,
}
void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
- changeSectionImpl(Section, Subsection);
-}
-
-bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
- uint32_t Subsection) {
assert(Section && "Cannot switch to a null section!");
getContext().clearDwarfLocSeen();
@@ -259,7 +263,7 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
Section->CurFragList = &Subsections[I].second;
CurFrag = Section->CurFragList->Tail;
- return getAssembler().registerSection(*Section);
+ getAssembler().registerSection(*Section);
}
void MCObjectStreamer::switchSectionNoPrint(MCSection *Section) {
@@ -291,18 +295,6 @@ bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
void MCObjectStreamer::emitInstruction(const MCInst &Inst,
const MCSubtargetInfo &STI) {
- const MCSection &Sec = *getCurrentSectionOnly();
- if (Sec.isVirtualSection()) {
- getContext().reportError(Inst.getLoc(), Twine(Sec.getVirtualSectionKind()) +
- " section '" + Sec.getName() +
- "' cannot have instructions");
- return;
- }
- emitInstructionImpl(Inst, STI);
-}
-
-void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
MCStreamer::emitInstruction(Inst, STI);
MCSection *Sec = getCurrentSectionOnly();
@@ -336,7 +328,7 @@ void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst,
void MCObjectStreamer::emitInstToData(const MCInst &Inst,
const MCSubtargetInfo &STI) {
- MCFragment *F = getOrCreateDataFragment();
+ MCFragment *F = getCurrentFragment();
// Append the instruction to the data fragment.
size_t FixupStartIndex = F->getFixups().size();
@@ -368,7 +360,7 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
const MCSubtargetInfo &STI) {
- auto *F = getOrCreateDataFragment();
+ auto *F = getCurrentFragment();
SmallVector<char, 16> Data;
SmallVector<MCFixup, 1> Fixups;
getAssembler().getEmitter().encodeInstruction(Inst, Data, Fixups, STI);
@@ -379,6 +371,7 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
F->setVarContents(Data);
F->setVarFixups(Fixups);
F->setInst(Inst);
+ newFragment();
}
void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
@@ -440,10 +433,11 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
return;
}
- auto *F = getOrCreateDataFragment();
+ auto *F = getCurrentFragment();
F->Kind = MCFragment::FT_Dwarf;
F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, SMLoc()));
F->setDwarfLineDelta(LineDelta);
+ newFragment();
}
void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,
@@ -471,9 +465,10 @@ void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,
void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
const MCSymbol *Label,
SMLoc Loc) {
- auto *F = getOrCreateDataFragment();
+ auto *F = getCurrentFragment();
F->Kind = MCFragment::FT_DwarfFrame;
F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, Loc));
+ newFragment();
}
void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
@@ -532,7 +527,7 @@ void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
void MCObjectStreamer::emitBytes(StringRef Data) {
MCDwarfLineEntry::make(this, getCurrentSectionOnly());
- MCFragment *DF = getOrCreateDataFragment();
+ MCFragment *DF = getCurrentFragment();
DF->appendContents(ArrayRef(Data.data(), Data.size()));
}
@@ -541,28 +536,21 @@ void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill,
unsigned MaxBytesToEmit) {
if (MaxBytesToEmit == 0)
MaxBytesToEmit = Alignment.value();
- insert(getContext().allocFragment<MCAlignFragment>(Alignment, Fill, FillLen,
- MaxBytesToEmit));
+ MCFragment *F = getCurrentFragment();
+ F->makeAlign(Alignment, Fill, FillLen, MaxBytesToEmit);
+ newFragment();
// Update the maximum alignment on the current section if necessary.
- MCSection *CurSec = getCurrentSectionOnly();
- CurSec->ensureMinAlignment(Alignment);
+ F->getParent()->ensureMinAlignment(Alignment);
}
void MCObjectStreamer::emitCodeAlignment(Align Alignment,
const MCSubtargetInfo *STI,
unsigned MaxBytesToEmit) {
+ auto *F = getCurrentFragment();
emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);
- auto *F = cast<MCAlignFragment>(getCurrentFragment());
- F->setEmitNops(true, STI);
- // With RISC-V style linker relaxation, mark the section as linker-relaxable
- // if the alignment is larger than the minimum NOP size.
- unsigned Size;
- if (getAssembler().getBackend().shouldInsertExtraNopBytesForCodeAlign(*F,
- Size)) {
- getCurrentSectionOnly()->setLinkerRelaxable();
- newFragment();
- }
+ F->u.align.EmitNops = true;
+ F->STI = STI;
}
void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 77bf843..eda5e8c 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -3404,11 +3404,10 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, uint8_t ValueSize) {
const MCSection *Section = getStreamer().getCurrentSectionOnly();
assert(Section && "must have section to emit alignment");
- if (HasFillExpr && FillExpr != 0 && Section->isVirtualSection()) {
+ if (HasFillExpr && FillExpr != 0 && Section->isBssSection()) {
ReturnVal |=
- Warning(FillExprLoc, "ignoring non-zero fill value in " +
- Section->getVirtualSectionKind() +
- " section '" + Section->getName() + "'");
+ Warning(FillExprLoc, "ignoring non-zero fill value in BSS section '" +
+ Section->getName() + "'");
FillExpr = 0;
}
@@ -4094,27 +4093,30 @@ bool AsmParser::parseDirectiveCVFPOData() {
}
/// parseDirectiveCFISections
-/// ::= .cfi_sections section [, section]
+/// ::= .cfi_sections section [, section][, section]
bool AsmParser::parseDirectiveCFISections() {
StringRef Name;
bool EH = false;
bool Debug = false;
+ bool SFrame = false;
if (!parseOptionalToken(AsmToken::EndOfStatement)) {
for (;;) {
if (parseIdentifier(Name))
- return TokError("expected .eh_frame or .debug_frame");
+ return TokError("expected .eh_frame, .debug_frame, or .sframe");
if (Name == ".eh_frame")
EH = true;
else if (Name == ".debug_frame")
Debug = true;
+ else if (Name == ".sframe")
+ SFrame = true;
if (parseOptionalToken(AsmToken::EndOfStatement))
break;
if (parseComma())
return true;
}
}
- getStreamer().emitCFISections(EH, Debug);
+ getStreamer().emitCFISections(EH, Debug, SFrame);
return false;
}
diff --git a/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp b/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
index 7f09349..d7b0546 100644
--- a/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
@@ -8,8 +8,8 @@
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCRegister.h"
-#include "llvm/MC/MCStreamer.h"
using namespace llvm;
@@ -25,8 +25,9 @@ MCSubtargetInfo &MCTargetAsmParser::copySTI() {
STI = &STICopy;
// The returned STI will likely be modified. Create a new fragment to prevent
// mixing STI values within a fragment.
- if (getStreamer().getCurrentFragment())
- getStreamer().newFragment();
+ auto &S = getStreamer();
+ if (S.isObj() && S.getCurrentFragment())
+ static_cast<MCObjectStreamer &>(S).newFragment();
return STICopy;
}
diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp
index 9367145..023f7f2 100644
--- a/llvm/lib/MC/MCSection.cpp
+++ b/llvm/lib/MC/MCSection.cpp
@@ -18,10 +18,10 @@
using namespace llvm;
-MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText,
- bool IsVirtual, MCSymbol *Begin)
+MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText, bool IsBss,
+ MCSymbol *Begin)
: Begin(Begin), HasInstructions(false), IsRegistered(false), IsText(IsText),
- IsVirtual(IsVirtual), LinkerRelaxable(false), Name(Name), Variant(V) {
+ IsBss(IsBss), LinkerRelaxable(false), Name(Name), Variant(V) {
// The initial subsection number is 0. Create a fragment list.
CurFragList = &Subsections.emplace_back(0u, FragList{}).second;
}
@@ -34,8 +34,6 @@ MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
bool MCSection::hasEnded() const { return End && End->isInSection(); }
-StringRef MCSection::getVirtualSectionKind() const { return "virtual"; }
-
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCSection::dump(
DenseMap<const MCFragment *, SmallVector<const MCSymbol *, 0>> *FragToSyms)
@@ -60,16 +58,6 @@ LLVM_DUMP_METHOD void MCSection::dump(
}
#endif
-void MCFragment::setContents(ArrayRef<char> Contents) {
- auto &S = getParent()->ContentStorage;
- if (ContentStart + Contents.size() > ContentEnd) {
- ContentStart = S.size();
- S.resize_for_overwrite(S.size() + Contents.size());
- }
- ContentEnd = ContentStart + Contents.size();
- llvm::copy(Contents, S.begin() + ContentStart);
-}
-
void MCFragment::setVarContents(ArrayRef<char> Contents) {
auto &S = getParent()->ContentStorage;
if (VarContentStart + Contents.size() > VarContentEnd) {
@@ -96,16 +84,6 @@ void MCFragment::appendFixups(ArrayRef<MCFixup> Fixups) {
FixupEnd = S.size();
}
-void MCFragment::setFixups(ArrayRef<MCFixup> Fixups) {
- auto &S = getParent()->FixupStorage;
- if (FixupStart + Fixups.size() > FixupEnd) {
- FixupStart = S.size();
- S.resize_for_overwrite(S.size() + Fixups.size());
- }
- FixupEnd = FixupStart + Fixups.size();
- llvm::copy(Fixups, S.begin() + FixupStart);
-}
-
void MCFragment::setVarFixups(ArrayRef<MCFixup> Fixups) {
auto &S = getParent()->FixupStorage;
if (VarFixupStart + Fixups.size() > VarFixupEnd) {
diff --git a/llvm/lib/MC/MCSectionCOFF.cpp b/llvm/lib/MC/MCSectionCOFF.cpp
index 94e29ce..5bf1473 100644
--- a/llvm/lib/MC/MCSectionCOFF.cpp
+++ b/llvm/lib/MC/MCSectionCOFF.cpp
@@ -115,7 +115,3 @@ void MCSectionCOFF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
}
bool MCSectionCOFF::useCodeAlign() const { return isText(); }
-
-StringRef MCSectionCOFF::getVirtualSectionKind() const {
- return "IMAGE_SCN_CNT_UNINITIALIZED_DATA";
-}
diff --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp
index 299fe40..ef33f9c 100644
--- a/llvm/lib/MC/MCSectionELF.cpp
+++ b/llvm/lib/MC/MCSectionELF.cpp
@@ -215,5 +215,3 @@ void MCSectionELF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
bool MCSectionELF::useCodeAlign() const {
return getFlags() & ELF::SHF_EXECINSTR;
}
-
-StringRef MCSectionELF::getVirtualSectionKind() const { return "SHT_NOBITS"; }
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index c3ecf8f..e14a32f 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -415,7 +415,7 @@ void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
void MCStreamer::emitConditionalAssignment(MCSymbol *Symbol,
const MCExpr *Value) {}
-void MCStreamer::emitCFISections(bool EH, bool Debug) {}
+void MCStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {}
void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) {
if (!FrameInfoStack.empty() &&
@@ -1404,7 +1404,7 @@ MCSymbol *MCStreamer::endSection(MCSection *Section) {
return Sym;
}
-void MCStreamer::insert(MCFragment *F) {
+void MCStreamer::addFragment(MCFragment *F) {
auto *Sec = CurFrag->getParent();
F->setParent(Sec);
F->setLayoutOrder(CurFrag->getLayoutOrder() + 1);
@@ -1413,10 +1413,6 @@ void MCStreamer::insert(MCFragment *F) {
Sec->curFragList()->Tail = F;
}
-void MCStreamer::newFragment() {
- insert(getContext().allocFragment<MCFragment>());
-}
-
static VersionTuple
targetVersionOrMinimumSupportedOSVersion(const Triple &Target,
VersionTuple TargetVersion) {
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 2adc291..ff95ff7 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -41,6 +41,7 @@ MCOPT(int, DwarfVersion)
MCOPT(bool, Dwarf64)
MCOPT(EmitDwarfUnwindType, EmitDwarfUnwind)
MCOPT(bool, EmitCompactUnwindNonCanonical)
+MCOPT(bool, EmitSFrameUnwind)
MCOPT(bool, ShowMCInst)
MCOPT(bool, FatalWarnings)
MCOPT(bool, NoWarn)
@@ -105,6 +106,11 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
false)); // By default, use DWARF for non-canonical personalities.
MCBINDOPT(EmitCompactUnwindNonCanonical);
+ static cl::opt<bool> EmitSFrameUnwind(
+ "gsframe", cl::desc("Whether to emit .sframe unwind sections."),
+ cl::init(false));
+ MCBINDOPT(EmitSFrameUnwind);
+
static cl::opt<bool> ShowMCInst(
"asm-show-inst",
cl::desc("Emit internal instruction representation to assembly file"));
@@ -188,6 +194,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
Options.X86Sse2Avx = getX86Sse2Avx();
Options.EmitDwarfUnwind = getEmitDwarfUnwind();
Options.EmitCompactUnwindNonCanonical = getEmitCompactUnwindNonCanonical();
+ Options.EmitSFrameUnwind = getEmitSFrameUnwind();
Options.AsSecureLogFile = getAsSecureLogFile();
return Options;
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index e8b26bf..72a8dd7 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -318,15 +318,13 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
// Emit the epilog instructions.
if (EnableUnwindV2) {
- MCFragment *DF = OS->getOrCreateDataFragment();
-
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)
diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp
index 3398775..9369bea 100644
--- a/llvm/lib/MC/MCWinCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp
@@ -153,7 +153,7 @@ void MCWinCOFFStreamer::initSections(bool NoExecStack,
}
void MCWinCOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
- changeSectionImpl(Section, Subsection);
+ MCObjectStreamer::changeSection(Section, Subsection);
// Ensure that the first and the second symbols relative to the section are
// the section symbol and the COMDAT symbol.
getAssembler().registerSymbol(*Section->getBeginSymbol());
@@ -278,35 +278,28 @@ void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {
void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) {
visitUsedSymbol(*Symbol);
- MCFragment *DF = getOrCreateDataFragment();
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 = getOrCreateDataFragment();
// 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 = getOrCreateDataFragment();
// 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 = getOrCreateDataFragment();
// 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 = getOrCreateDataFragment();
// 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,
diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp
index 4d45296..63381b4 100644
--- a/llvm/lib/MC/MCXCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCXCOFFStreamer.cpp
@@ -89,7 +89,7 @@ void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility(
void MCXCOFFStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
// Add a Fixup here to later record a relocation of type R_REF to prevent the
// ref symbol from being garbage collected (by the binder).
- MCFragment *DF = getOrCreateDataFragment();
+ MCFragment *DF = getCurrentFragment();
const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
std::optional<MCFixupKind> MaybeKind =
getAssembler().getBackend().getFixupKind("R_REF");
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index 3291dd7..48d2fc6 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -131,7 +131,7 @@ uint64_t MachObjectWriter::getPaddingSize(const MCAssembler &Asm,
return 0;
const MCSection &NextSec = *SectionOrder[Next];
- if (NextSec.isVirtualSection())
+ if (NextSec.isBssSection())
return 0;
return offsetToAlignment(EndAddr, NextSec.getAlign());
}
@@ -267,7 +267,7 @@ void MachObjectWriter::writeSection(const MCAssembler &Asm,
const MCSectionMachO &Section = cast<MCSectionMachO>(Sec);
// The offset is unused for virtual sections.
- if (Section.isVirtualSection()) {
+ if (Section.isBssSection()) {
assert(Asm.getSectionFileSize(Sec) == 0 && "Invalid file size!");
FileOffset = 0;
}
@@ -682,13 +682,13 @@ void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm) {
unsigned i = 0;
// Compute the section layout order. Virtual sections must go last.
for (MCSection &Sec : Asm) {
- if (!Sec.isVirtualSection()) {
+ if (!Sec.isBssSection()) {
SectionOrder.push_back(&Sec);
cast<MCSectionMachO>(Sec).setLayoutOrder(i++);
}
}
for (MCSection &Sec : Asm) {
- if (Sec.isVirtualSection()) {
+ if (Sec.isBssSection()) {
SectionOrder.push_back(&Sec);
cast<MCSectionMachO>(Sec).setLayoutOrder(i++);
}
@@ -797,11 +797,8 @@ uint64_t MachObjectWriter::writeObject() {
UndefinedSymbolData);
if (!CGProfile.empty()) {
- MCSection *CGProfileSection = getContext().getMachOSection(
- "__LLVM", "__cg_profile", 0, SectionKind::getMetadata());
- auto &Frag = *CGProfileSection->begin();
- Frag.clearContents();
- raw_svector_ostream OS(Frag.getContentsForAppending());
+ SmallString<0> Content;
+ raw_svector_ostream OS(Content);
for (const MCObjectWriter::CGProfileEntry &CGPE : CGProfile) {
uint32_t FromIndex = CGPE.From->getSymbol().getIndex();
uint32_t ToIndex = CGPE.To->getSymbol().getIndex();
@@ -809,7 +806,9 @@ uint64_t MachObjectWriter::writeObject() {
support::endian::write(OS, ToIndex, W.Endian);
support::endian::write(OS, CGPE.Count, W.Endian);
}
- Frag.doneAppending();
+ MCSection *Sec = getContext().getMachOSection("__LLVM", "__cg_profile", 0,
+ SectionKind::getMetadata());
+ llvm::copy(OS.str(), Sec->curFragList()->Head->getContents().data());
}
unsigned NumSections = Asm.end() - Asm.begin();
@@ -883,7 +882,7 @@ uint64_t MachObjectWriter::writeObject() {
VMSize = std::max(VMSize, Address + Size);
- if (Sec.isVirtualSection())
+ if (Sec.isBssSection())
continue;
SectionDataSize = std::max(SectionDataSize, Address + Size);
@@ -915,7 +914,7 @@ uint64_t MachObjectWriter::writeObject() {
unsigned Flags = Sec.getTypeAndAttributes();
if (Sec.hasInstructions())
Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS;
- if (!cast<MCSectionMachO>(Sec).isVirtualSection() &&
+ if (!cast<MCSectionMachO>(Sec).isBssSection() &&
!isUInt<32>(SectionStart)) {
getContext().reportError(
SMLoc(), "cannot encode offset of section; object file too large");
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 7af240a..3b99af4 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -696,14 +696,15 @@ static void addData(SmallVectorImpl<char> &DataBytes,
if (Frag.hasInstructions())
report_fatal_error("only data supported in data sections");
- if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
- if (Align->getFillLen() != 1)
+ llvm::append_range(DataBytes, Frag.getContents());
+ if (Frag.getKind() == MCFragment::FT_Align) {
+ if (Frag.getAlignFillLen() != 1)
report_fatal_error("only byte values supported for alignment");
// If nops are requested, use zeros, as this is the data section.
- uint8_t Value = Align->hasEmitNops() ? 0 : Align->getFill();
+ uint8_t Value = Frag.hasAlignEmitNops() ? 0 : Frag.getAlignFill();
uint64_t Size =
- std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()),
- DataBytes.size() + Align->getMaxBytesToEmit());
+ std::min<uint64_t>(alignTo(DataBytes.size(), Frag.getAlignment()),
+ DataBytes.size() + Frag.getAlignMaxBytesToEmit());
DataBytes.resize(Size, Value);
} else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
int64_t NumValues;
@@ -711,12 +712,10 @@ static void addData(SmallVectorImpl<char> &DataBytes,
llvm_unreachable("The fill should be an assembler constant");
DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
Fill->getValue());
+ } else if (Frag.getKind() == MCFragment::FT_LEB) {
+ llvm::append_range(DataBytes, Frag.getVarContents());
} else {
- llvm::append_range(DataBytes, Frag.getContents());
- if (Frag.getKind() == MCFragment::FT_LEB)
- llvm::append_range(DataBytes, Frag.getVarContents());
- else
- assert(Frag.getKind() == MCFragment::FT_Data);
+ assert(Frag.getKind() == MCFragment::FT_Data);
}
}
@@ -1858,23 +1857,9 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
auto IT = WS.begin();
if (IT == WS.end())
continue;
- const MCFragment &EmptyFrag = *IT;
- if (EmptyFrag.getKind() != MCFragment::FT_Data)
- report_fatal_error(".init_array section should be aligned");
-
- const MCFragment *nextFrag = EmptyFrag.getNext();
- while (nextFrag != nullptr) {
- const MCFragment &AlignFrag = *nextFrag;
- if (AlignFrag.getKind() != MCFragment::FT_Align)
- report_fatal_error(".init_array section should be aligned");
- if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
- Align(is64Bit() ? 8 : 4))
- report_fatal_error(
- ".init_array section should be aligned for pointers");
-
- const MCFragment &Frag = *AlignFrag.getNext();
- nextFrag = Frag.getNext();
- if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
+ for (auto *Frag = &*IT; Frag; Frag = Frag->getNext()) {
+ if (Frag->hasInstructions() || (Frag->getKind() != MCFragment::FT_Align &&
+ Frag->getKind() != MCFragment::FT_Data))
report_fatal_error("only data supported in .init_array section");
uint16_t Priority = UINT16_MAX;
@@ -1886,9 +1871,8 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
report_fatal_error("invalid .init_array section priority");
}
- const auto &DataFrag = Frag;
- assert(llvm::all_of(DataFrag.getContents(), [](char C) { return !C; }));
- for (const MCFixup &Fixup : DataFrag.getFixups()) {
+ assert(llvm::all_of(Frag->getContents(), [](char C) { return !C; }));
+ for (const MCFixup &Fixup : Frag->getFixups()) {
assert(Fixup.getKind() ==
MCFixup::getDataKindForSize(is64Bit() ? 8 : 4));
const MCExpr *Expr = Fixup.getValue();
diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index ee4d957..6ad4334 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -179,7 +179,7 @@ private:
void SetSymbolName(COFFSymbol &S);
void SetSectionName(COFFSection &S);
- bool IsPhysicalSection(COFFSection *S);
+ bool isUninitializedData(const COFFSection &S);
// Entity writing methods.
void WriteFileHeader(const COFF::header &Header);
@@ -453,8 +453,8 @@ void WinCOFFWriter::SetSymbolName(COFFSymbol &S) {
std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
}
-bool WinCOFFWriter::IsPhysicalSection(COFFSection *S) {
- return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) ==
+bool WinCOFFWriter::isUninitializedData(const COFFSection &S) {
+ return (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) !=
0;
}
@@ -606,6 +606,9 @@ void WinCOFFWriter::writeSection(const COFFSection &Sec) {
assert(AuxSyms.size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition);
AuxSymbol &SecDef = AuxSyms[0];
SecDef.Aux.SectionDefinition.CheckSum = CRC;
+ } else if (isUninitializedData(Sec)) {
+ // Error if fixups or non-zero bytes are present.
+ writeSectionContents(*Sec.MCSection);
}
// Write relocations for this section.
@@ -745,7 +748,7 @@ void WinCOFFWriter::assignFileOffsets() {
Sec->Header.SizeOfRawData = Asm->getSectionAddressSize(Section);
- if (IsPhysicalSection(Sec)) {
+ if (!isUninitializedData(*Sec)) {
Sec->Header.PointerToRawData = Offset;
Offset += Sec->Header.SizeOfRawData;
}
@@ -1067,10 +1070,8 @@ uint64_t WinCOFFWriter::writeObject() {
// Create the contents of the .llvm_addrsig section.
if (Mode != DwoOnly && OWriter.getEmitAddrsigSection()) {
- auto *Sec = getContext().getCOFFSection(".llvm_addrsig",
- COFF::IMAGE_SCN_LNK_REMOVE);
- auto *Frag = Sec->curFragList()->Head;
- raw_svector_ostream OS(Frag->getContentsForAppending());
+ SmallString<0> Content;
+ raw_svector_ostream OS(Content);
for (const MCSymbol *S : OWriter.AddrsigSyms) {
if (!S->isRegistered())
continue;
@@ -1085,15 +1086,15 @@ uint64_t WinCOFFWriter::writeObject() {
"executePostLayoutBinding!");
encodeULEB128(SectionMap[TargetSection]->Symbol->getIndex(), OS);
}
- Frag->doneAppending();
+ auto *Sec = getContext().getCOFFSection(".llvm_addrsig",
+ COFF::IMAGE_SCN_LNK_REMOVE);
+ Sec->curFragList()->Tail->setVarContents(OS.str());
}
// Create the contents of the .llvm.call-graph-profile section.
if (Mode != DwoOnly && !OWriter.getCGProfile().empty()) {
- auto *Sec = getContext().getCOFFSection(".llvm.call-graph-profile",
- COFF::IMAGE_SCN_LNK_REMOVE);
- auto *Frag = Sec->curFragList()->Head;
- raw_svector_ostream OS(Frag->getContentsForAppending());
+ SmallString<0> Content;
+ raw_svector_ostream OS(Content);
for (const auto &CGPE : OWriter.getCGProfile()) {
uint32_t FromIndex = CGPE.From->getSymbol().getIndex();
uint32_t ToIndex = CGPE.To->getSymbol().getIndex();
@@ -1101,7 +1102,9 @@ uint64_t WinCOFFWriter::writeObject() {
support::endian::write(OS, ToIndex, W.Endian);
support::endian::write(OS, CGPE.Count, W.Endian);
}
- Frag->doneAppending();
+ auto *Sec = getContext().getCOFFSection(".llvm.call-graph-profile",
+ COFF::IMAGE_SCN_LNK_REMOVE);
+ Sec->curFragList()->Tail->setVarContents(OS.str());
}
assignFileOffsets();