[llvm] 78207e1 - [NFC][XCOFF][AIX] Serialize object file writing for each CsectGroup
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 24 08:39:47 PDT 2019
Author: jasonliu
Date: 2019-10-24T15:38:50Z
New Revision: 78207e1f234eede120beaf730dfb7bb9d4e00a1b
URL: https://github.com/llvm/llvm-project/commit/78207e1f234eede120beaf730dfb7bb9d4e00a1b
DIFF: https://github.com/llvm/llvm-project/commit/78207e1f234eede120beaf730dfb7bb9d4e00a1b.diff
LOG: [NFC][XCOFF][AIX] Serialize object file writing for each CsectGroup
Summary:
Right now we handle each CsectGroup(ProgramCodeCsects, BSSCsects)
individually when assigning indices, writing symbol table, and
writing section raw data. However, there is already a pattern there,
and we could common up those actions for every CsectGroup. This will
make adding new CsectGroup(Read Write data, Read only data, TC/TOC,
mergeable string) easier, and less error prone.
Reviewed by: sfertile, daltenty, DiggerLin
Approved by: daltenty
Differential Revision: https://reviews.llvm.org/D69112
Added:
Modified:
llvm/lib/MC/XCOFFObjectWriter.cpp
Removed:
################################################################################
diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index 353c21068735..2868972f71ce 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -44,6 +44,7 @@ using namespace llvm;
namespace {
constexpr unsigned DefaultSectionAlign = 4;
+constexpr int16_t MaxSectionIndex = INT16_MAX;
// Packs the csect's alignment and type into a byte.
uint8_t getEncodedType(const MCSectionXCOFF *);
@@ -73,6 +74,22 @@ struct ControlSection {
: MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
};
+// Type to be used for a container representing a set of csects with
+// (approximately) the same storage mapping class. For example all the csects
+// with a storage mapping class of `xmc_pr` will get placed into the same
+// container.
+struct CsectGroup {
+ enum LabelDefinitionSupport : bool {
+ LabelDefSupported = true,
+ LabelDefUnsupported = false
+ };
+
+ const LabelDefinitionSupport SupportLabelDef;
+ std::deque<ControlSection> Csects;
+};
+
+using CsectGroups = std::deque<CsectGroup *>;
+
// Represents the data related to a section excluding the csects that make up
// the raw data of the section. The csects are stored separately as not all
// sections contain csects, and some sections contain csects which are better
@@ -94,49 +111,63 @@ struct Section {
// Virtual sections do not need storage allocated in the object file.
const bool IsVirtual;
+ // XCOFF has special section numbers for symbols:
+ // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
+ // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
+ // relocatable.
+ // 0 Specifies N_UNDEF, an undefined external symbol.
+ // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
+ // hasn't been initialized.
+ static constexpr int16_t UninitializedIndex =
+ XCOFF::ReservedSectionNum::N_DEBUG - 1;
+
+ CsectGroups Groups;
+
void reset() {
Address = 0;
Size = 0;
FileOffsetToData = 0;
FileOffsetToRelocations = 0;
RelocationCount = 0;
- Index = -1;
+ Index = UninitializedIndex;
+ // Clear any csects we have stored.
+ for (auto *Group : Groups)
+ Group->Csects.clear();
}
- Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual)
+ Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
+ CsectGroups Groups)
: Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
- RelocationCount(0), Flags(Flags), Index(-1), IsVirtual(IsVirtual) {
+ RelocationCount(0), Flags(Flags), Index(UninitializedIndex),
+ IsVirtual(IsVirtual), Groups(Groups) {
strncpy(Name, N, XCOFF::NameSize);
}
};
class XCOFFObjectWriter : public MCObjectWriter {
- // Type to be used for a container representing a set of csects with
- // (approximately) the same storage mapping class. For example all the csects
- // with a storage mapping class of `xmc_pr` will get placed into the same
- // container.
- using CsectGroup = std::deque<ControlSection>;
+
+ uint32_t SymbolTableEntryCount = 0;
+ uint32_t SymbolTableOffset = 0;
support::endian::Writer W;
std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
StringTableBuilder Strings;
- // The non-empty sections, in the order they will appear in the section header
- // table.
- std::vector<Section *> Sections;
+ // CsectGroups. These store the csects which make up
diff erent parts of
+ // the sections. Should have one for each set of csects that get mapped into
+ // the same section and get handled in a 'similar' way.
+ CsectGroup ProgramCodeCsects{CsectGroup::LabelDefSupported};
+ CsectGroup BSSCsects{CsectGroup::LabelDefUnsupported};
// The Predefined sections.
Section Text;
Section BSS;
- // CsectGroups. These store the csects which make up
diff erent parts of
- // the sections. Should have one for each set of csects that get mapped into
- // the same section and get handled in a 'similar' way.
- CsectGroup ProgramCodeCsects;
- CsectGroup BSSCsects;
+ // All the XCOFF sections, in the order they will appear in the section header
+ // table.
+ std::array<Section *const, 2> Sections{&Text, &BSS};
- uint32_t SymbolTableEntryCount = 0;
- uint32_t SymbolTableOffset = 0;
+ CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
virtual void reset() override;
@@ -190,18 +221,15 @@ XCOFFObjectWriter::XCOFFObjectWriter(
std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
: W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
Strings(StringTableBuilder::XCOFF),
- Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false),
- BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true) {}
+ Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
+ CsectGroups{&ProgramCodeCsects}),
+ BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
+ CsectGroups{&BSSCsects}) {}
void XCOFFObjectWriter::reset() {
// Reset any sections we have written to, and empty the section header table.
for (auto *Sec : Sections)
Sec->reset();
- Sections.clear();
-
- // Clear any csects we have stored.
- ProgramCodeCsects.clear();
- BSSCsects.clear();
// Reset the symbol table and string table.
SymbolTableEntryCount = 0;
@@ -211,6 +239,27 @@ void XCOFFObjectWriter::reset() {
MCObjectWriter::reset();
}
+CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
+ switch (MCSec->getMappingClass()) {
+ case XCOFF::XMC_PR:
+ assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
+ "Only an initialized csect can contain program code.");
+ return ProgramCodeCsects;
+ case XCOFF::XMC_RW:
+ if (XCOFF::XTY_CM == MCSec->getCSectType())
+ return BSSCsects;
+
+ report_fatal_error("Unhandled mapping of read-write csect to section.");
+ case XCOFF::XMC_BS:
+ assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
+ "Mapping invalid csect. CSECT with bss storage class must be "
+ "common type.");
+ return BSSCsects;
+ default:
+ report_fatal_error("Unhandled mapping of csect to section.");
+ }
+}
+
void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
if (TargetObjectWriter->is64Bit())
@@ -231,33 +280,13 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
if (nameShouldBeInStringTable(MCSec->getSectionName()))
Strings.add(MCSec->getSectionName());
- switch (MCSec->getMappingClass()) {
- case XCOFF::XMC_PR:
- assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
- "Only an initialized csect can contain program code.");
- ProgramCodeCsects.emplace_back(MCSec);
- WrapperMap[MCSec] = &ProgramCodeCsects.back();
- break;
- case XCOFF::XMC_RW:
- if (XCOFF::XTY_CM == MCSec->getCSectType()) {
- BSSCsects.emplace_back(MCSec);
- WrapperMap[MCSec] = &BSSCsects.back();
- break;
- }
- report_fatal_error("Unhandled mapping of read-write csect to section.");
- case XCOFF::XMC_TC0:
- // TODO FIXME Handle emiting the TOC base.
- break;
- case XCOFF::XMC_BS:
- assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
- "Mapping invalid csect. CSECT with bss storage class must be "
- "common type.");
- BSSCsects.emplace_back(MCSec);
- WrapperMap[MCSec] = &BSSCsects.back();
- break;
- default:
- report_fatal_error("Unhandled mapping of csect to section.");
- }
+ // TODO FIXME Handle emiting the TOC base.
+ if (MCSec->getMappingClass() == XCOFF::XMC_TC0)
+ continue;
+
+ CsectGroup &Group = getCsectGroup(MCSec);
+ Group.Csects.emplace_back(MCSec);
+ WrapperMap[MCSec] = &Group.Csects.back();
}
for (const MCSymbol &S : Asm.symbols()) {
@@ -292,21 +321,28 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
const MCAsmLayout &Layout) {
- // Write the program code control sections one at a time.
- uint32_t CurrentAddressLocation = Text.Address;
- for (const auto &Csect : ProgramCodeCsects) {
- if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
- W.OS.write_zeros(PaddingSize);
- Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
- CurrentAddressLocation = Csect.Address + Csect.Size;
- }
+ uint32_t CurrentAddressLocation = 0;
+ for (const auto *Section : Sections) {
+ // Nothing to write for this Section.
+ if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
+ continue;
+
+ assert(CurrentAddressLocation == Section->Address &&
+ "We should have no padding between sections.");
+ for (const auto *Group : Section->Groups) {
+ for (const auto &Csect : Group->Csects) {
+ if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
+ W.OS.write_zeros(PaddingSize);
+ Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
+ CurrentAddressLocation = Csect.Address + Csect.Size;
+ }
+ }
- if (Text.Index != -1) {
// The size of the tail padding in a section is the end virtual address of
// the current section minus the the end virtual address of the last csect
// in that section.
if (uint32_t PaddingSize =
- Text.Address + Text.Size - CurrentAddressLocation)
+ Section->Address + Section->Size - CurrentAddressLocation)
W.OS.write_zeros(PaddingSize);
}
}
@@ -472,25 +508,28 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
}
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
- // Print out symbol table for the program code.
- for (const auto &Csect : ProgramCodeCsects) {
- // Write out the control section first and then each symbol in it.
- writeSymbolTableEntryForControlSection(Csect, Text.Index,
- Csect.MCCsect->getStorageClass());
- for (const auto &Sym : Csect.Syms)
- writeSymbolTableEntryForCsectMemberLabel(
- Sym, Csect, Text.Index, Layout.getSymbolOffset(*Sym.MCSym));
- }
-
- // The BSS Section is special in that the csects must contain a single symbol,
- // and the contained symbol cannot be represented in the symbol table as a
- // label definition.
- for (auto &Csect : BSSCsects) {
- assert(Csect.Syms.size() == 1 &&
- "Uninitialized csect cannot contain more then 1 symbol.");
- Symbol &Sym = Csect.Syms.back();
- writeSymbolTableEntryForControlSection(Csect, BSS.Index,
- Sym.getStorageClass());
+ for (const auto *Section : Sections) {
+ for (const auto *Group : Section->Groups) {
+ if (Group->Csects.empty())
+ continue;
+
+ const bool SupportLabelDef = Group->SupportLabelDef;
+ const int16_t SectionIndex = Section->Index;
+ for (const auto &Csect : Group->Csects) {
+ // Write out the control section first and then each symbol in it.
+ writeSymbolTableEntryForControlSection(
+ Csect, SectionIndex, Csect.MCCsect->getStorageClass());
+ if (!SupportLabelDef) {
+ assert(Csect.Syms.size() == 1 && "Csect should only contain 1 symbol "
+ "which is its label definition.");
+ continue;
+ }
+
+ for (const auto Sym : Csect.Syms)
+ writeSymbolTableEntryForCsectMemberLabel(
+ Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
+ }
+ }
}
}
@@ -500,64 +539,59 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
// section header table.
uint32_t Address = 0;
// Section indices are 1-based in XCOFF.
- int16_t SectionIndex = 1;
+ int32_t SectionIndex = 1;
// The first symbol table entry is for the file name. We are not emitting it
// yet, so start at index 0.
uint32_t SymbolTableIndex = 0;
- // Text section comes first.
- if (!ProgramCodeCsects.empty()) {
- Sections.push_back(&Text);
- Text.Index = SectionIndex++;
- for (auto &Csect : ProgramCodeCsects) {
- const MCSectionXCOFF *MCSec = Csect.MCCsect;
- Csect.Address = alignTo(Address, MCSec->getAlignment());
- Csect.Size = Layout.getSectionAddressSize(MCSec);
- Address = Csect.Address + Csect.Size;
- Csect.SymbolTableIndex = SymbolTableIndex;
- // 1 main and 1 auxiliary symbol table entry for the csect.
- SymbolTableIndex += 2;
- for (auto &Sym : Csect.Syms) {
- Sym.SymbolTableIndex = SymbolTableIndex;
- // 1 main and 1 auxiliary symbol table entry for each contained symbol
+ for (auto *Section : Sections) {
+ const bool IsEmpty =
+ llvm::all_of(Section->Groups, [](const CsectGroup *Group) {
+ return Group->Csects.empty();
+ });
+ if (IsEmpty)
+ continue;
+
+ if (SectionIndex > MaxSectionIndex)
+ report_fatal_error("Section index overflow!");
+ Section->Index = SectionIndex++;
+
+ bool SectionAddressSet = false;
+ for (auto *Group : Section->Groups) {
+ if (Group->Csects.empty())
+ continue;
+
+ const bool SupportLabelDef = Group->SupportLabelDef;
+ for (auto &Csect : Group->Csects) {
+ const MCSectionXCOFF *MCSec = Csect.MCCsect;
+ Csect.Address = alignTo(Address, MCSec->getAlignment());
+ Csect.Size = Layout.getSectionAddressSize(MCSec);
+ Address = Csect.Address + Csect.Size;
+ Csect.SymbolTableIndex = SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for the csect.
SymbolTableIndex += 2;
- }
- }
- Address = alignTo(Address, DefaultSectionAlign);
- // The first csect of a section can be aligned by adjusting the virtual
- // address of its containing section instead of writing zeroes into the
- // object file.
- Text.Address = ProgramCodeCsects.front().Address;
+ if (!SupportLabelDef)
+ continue;
- Text.Size = Address - Text.Address;
- }
+ for (auto &Sym : Csect.Syms) {
+ Sym.SymbolTableIndex = SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for each contained
+ // symbol.
+ SymbolTableIndex += 2;
+ }
+ }
- // Data section Second. TODO
-
- // BSS Section third.
- if (!BSSCsects.empty()) {
- Sections.push_back(&BSS);
- BSS.Index = SectionIndex++;
- for (auto &Csect : BSSCsects) {
- const MCSectionXCOFF *MCSec = Csect.MCCsect;
- Csect.Address = alignTo(Address, MCSec->getAlignment());
- Csect.Size = Layout.getSectionAddressSize(MCSec);
- Address = Csect.Address + Csect.Size;
- Csect.SymbolTableIndex = SymbolTableIndex;
- // 1 main and 1 auxiliary symbol table entry for the csect.
- SymbolTableIndex += 2;
-
- assert(Csect.Syms.size() == 1 &&
- "csect in the BSS can only contain a single symbol.");
- Csect.Syms[0].SymbolTableIndex = Csect.SymbolTableIndex;
+ if (!SectionAddressSet) {
+ Section->Address = Group->Csects.front().Address;
+ SectionAddressSet = true;
+ }
}
- // Pad out Address to the default alignment. This is to match how the system
- // assembler handles the .bss section. Its size is always a multiple of 4.
- Address = alignTo(Address, DefaultSectionAlign);
- BSS.Address = BSSCsects.front().Address;
- BSS.Size = Address - BSS.Address;
+ // Make sure the address of the next section aligned to
+ // DefaultSectionAlign.
+ Address = alignTo(Address, DefaultSectionAlign);
+ Section->Size = Address - Section->Address;
}
SymbolTableEntryCount = SymbolTableIndex;
More information about the llvm-commits
mailing list