diff options
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 219 | ||||
-rw-r--r-- | llvm/lib/MC/MCCodeView.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/MC/MCDwarf.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/MC/MCELFStreamer.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/MC/MCExpr.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/MC/MCFragment.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/MC/MCMachOStreamer.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 98 | ||||
-rw-r--r-- | llvm/lib/MC/MCParser/AsmParser.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/MC/MCParser/MCTargetAsmParser.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/MC/MCSection.cpp | 28 | ||||
-rw-r--r-- | llvm/lib/MC/MCSectionCOFF.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/MC/MCSectionELF.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/MC/MCStreamer.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/MC/MCTargetOptionsCommandFlags.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/MC/MCWin64EH.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/MC/MCWinCOFFStreamer.cpp | 40 | ||||
-rw-r--r-- | llvm/lib/MC/MCXCOFFStreamer.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/MC/MachObjectWriter.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/MC/WasmObjectWriter.cpp | 44 | ||||
-rw-r--r-- | llvm/lib/MC/WinCOFFObjectWriter.cpp | 31 |
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(); |