Skip to content

Commit

Permalink
Implement -frecord-command-line for XCOFF integrated assembler path
Browse files Browse the repository at this point in the history
The patch D153600 implemented `-frecord-command-line` for the XCOFF direct assembly path. This patch adds support for the XCOFF integrated assembly path.

Reviewed By: scott.linder

Differential Revision: https://reviews.llvm.org/D154921
  • Loading branch information
jakeegan committed Jul 20, 2023
1 parent cf26941 commit 311abf5
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 9 deletions.
3 changes: 3 additions & 0 deletions llvm/include/llvm/MC/MCObjectWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class MCObjectWriter {
unsigned FunctionSize, bool hasDebug) {
report_fatal_error("addExceptionEntry is only supported on XCOFF targets");
}
virtual void addCInfoSymEntry(StringRef Name, StringRef Metadata) {
report_fatal_error("addCInfoSymEntry is only supported on XCOFF targets");
}
/// Write the object file and returns the number of bytes written.
///
/// This routine is called by the assembler after layout and relaxation is
Expand Down
5 changes: 1 addition & 4 deletions llvm/include/llvm/MC/MCXCOFFStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ class MCXCOFFStreamer : public MCObjectStreamer {
void emitXCOFFExceptDirective(const MCSymbol *Symbol, const MCSymbol *Trap,
unsigned Lang, unsigned Reason,
unsigned FunctionSize, bool hasDebug) override;
void emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) override {
report_fatal_error("emitXCOFFCInfoSym is not implemented yet on "
"object generation path");
}
void emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) override;
};

} // end namespace llvm
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/MC/MCXCOFFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ void MCXCOFFStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
FunctionSize, hasDebug);
}

void MCXCOFFStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
getAssembler().getWriter().addCInfoSymEntry(Name, Metadata);
}

void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Align ByteAlignment) {
getAssembler().registerSymbol(*Symbol);
Expand Down
115 changes: 114 additions & 1 deletion llvm/lib/MC/XCOFFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,42 @@ struct ExceptionSectionEntry : public SectionEntry {
virtual ~ExceptionSectionEntry() = default;
};

struct CInfoSymInfo {
// Name of the C_INFO symbol associated with the section
std::string Name;
std::string Metadata;
// Offset into the start of the metadata in the section
uint64_t Offset;

CInfoSymInfo(std::string Name, std::string Metadata)
: Name(Name), Metadata(Metadata) {}
// Metadata needs to be padded out to an even word size.
uint32_t paddingSize() const {
return alignTo(Metadata.size(), sizeof(uint32_t)) - Metadata.size();
};

// Total size of the entry, including the 4 byte length
uint32_t size() const {
return Metadata.size() + paddingSize() + sizeof(uint32_t);
};
};

struct CInfoSymSectionEntry : public SectionEntry {
std::unique_ptr<CInfoSymInfo> Entry;

CInfoSymSectionEntry(StringRef N, int32_t Flags) : SectionEntry(N, Flags) {}
virtual ~CInfoSymSectionEntry() = default;
void addEntry(std::unique_ptr<CInfoSymInfo> NewEntry) {
Entry = std::move(NewEntry);
Entry->Offset = sizeof(uint32_t);
Size += Entry->size();
}
void reset() override {
SectionEntry::reset();
Entry.reset();
}
};

class XCOFFObjectWriter : public MCObjectWriter {

uint32_t SymbolTableEntryCount = 0;
Expand Down Expand Up @@ -309,6 +345,7 @@ class XCOFFObjectWriter : public MCObjectWriter {
std::vector<SectionEntry> OverflowSections;

ExceptionSectionEntry ExceptionSection;
CInfoSymSectionEntry CInfoSymSection;

CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);

Expand Down Expand Up @@ -350,6 +387,10 @@ class XCOFFObjectWriter : public MCObjectWriter {
void writeSectionForExceptionSectionEntry(
const MCAssembler &Asm, const MCAsmLayout &Layout,
ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation);
void writeSectionForCInfoSymSectionEntry(const MCAssembler &Asm,
const MCAsmLayout &Layout,
CInfoSymSectionEntry &CInfoSymEntry,
uint64_t &CurrentAddressLocation);
void writeSymbolTable(const MCAsmLayout &Layout);
void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
uint64_t NumberOfRelocEnt = 0);
Expand Down Expand Up @@ -390,6 +431,7 @@ class XCOFFObjectWriter : public MCObjectWriter {
unsigned getExceptionSectionSize();
unsigned getExceptionOffset(const MCSymbol *Symbol);

void addCInfoSymEntry(StringRef Name, StringRef Metadata) override;
size_t auxiliaryHeaderSize() const {
// 64-bit object files have no auxiliary header.
return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0;
Expand Down Expand Up @@ -418,7 +460,8 @@ XCOFFObjectWriter::XCOFFObjectWriter(
CsectGroups{&TDataCsects}),
TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
CsectGroups{&TBSSCsects}),
ExceptionSection(".except", XCOFF::STYP_EXCEPT) {}
ExceptionSection(".except", XCOFF::STYP_EXCEPT),
CInfoSymSection(".info", XCOFF::STYP_INFO) {}

void XCOFFObjectWriter::reset() {
// Clear the mappings we created.
Expand All @@ -434,6 +477,7 @@ void XCOFFObjectWriter::reset() {
for (auto &OverflowSec : OverflowSections)
OverflowSec.reset();
ExceptionSection.reset();
CInfoSymSection.reset();

// Reset states in XCOFFObjectWriter.
SymbolTableEntryCount = 0;
Expand Down Expand Up @@ -581,6 +625,10 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
Strings.add(XSym->getSymbolTableName());
}

std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry;
if (CISI && nameShouldBeInStringTable(CISI->Name))
Strings.add(CISI->Name);

FileNames = Asm.getFileNames();
// Emit ".file" as the source file name when there is no file name.
if (FileNames.empty())
Expand Down Expand Up @@ -743,6 +791,8 @@ void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
CurrentAddressLocation);
writeSectionForExceptionSectionEntry(Asm, Layout, ExceptionSection,
CurrentAddressLocation);
writeSectionForCInfoSymSectionEntry(Asm, Layout, CInfoSymSection,
CurrentAddressLocation);
}

uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
Expand Down Expand Up @@ -1012,6 +1062,8 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
writeSectionHeader(&OverflowSec);
if (hasExceptionSection())
writeSectionHeader(&ExceptionSection);
if (CInfoSymSection.Entry)
writeSectionHeader(&CInfoSymSection);
}

void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
Expand Down Expand Up @@ -1060,6 +1112,12 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
/*NumberOfAuxEntries=*/0);
}

if (CInfoSymSection.Entry)
writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset,
CInfoSymSection.Index,
/*SymbolType=*/0, XCOFF::C_INFO,
/*NumberOfAuxEntries=*/0);

for (const auto &Csect : UndefinedCsects) {
writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
Csect.MCSec->getStorageClass());
Expand Down Expand Up @@ -1197,6 +1255,9 @@ void XCOFFObjectWriter::finalizeSectionInfo() {
if (hasExceptionSection())
RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer);

if (CInfoSymSection.Entry)
RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer);

for (auto *Sec : Sections) {
if (Sec->Index != SectionEntry::UninitializedIndex)
calcOffsetToRelocations(Sec, RawPointer);
Expand Down Expand Up @@ -1258,10 +1319,19 @@ unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol *Symbol) {
: XCOFF::ExceptionSectionEntrySize32);
}

void XCOFFObjectWriter::addCInfoSymEntry(StringRef Name, StringRef Metadata) {
assert(!CInfoSymSection.Entry && "Multiple entries are not supported");
CInfoSymSection.addEntry(
std::make_unique<CInfoSymInfo>(Name.str(), Metadata.str()));
}

void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
// The symbol table starts with all the C_FILE symbols.
uint32_t SymbolTableIndex = FileNames.size();

if (CInfoSymSection.Entry)
SymbolTableIndex++;

// Calculate indices for undefined symbols.
for (auto &Csect : UndefinedCsects) {
Csect.Size = 0;
Expand Down Expand Up @@ -1418,6 +1488,14 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
Address = alignTo(Address, DefaultSectionAlign);
}

if (CInfoSymSection.Entry) {
CInfoSymSection.Index = SectionIndex++;
SectionCount++;
CInfoSymSection.Address = 0;
Address += CInfoSymSection.Size;
Address = alignTo(Address, DefaultSectionAlign);
}

SymbolTableEntryCount = SymbolTableIndex;
}

Expand Down Expand Up @@ -1519,6 +1597,41 @@ void XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
CurrentAddressLocation += getExceptionSectionSize();
}

void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry(
const MCAssembler &Asm, const MCAsmLayout &Layout,
CInfoSymSectionEntry &CInfoSymEntry, uint64_t &CurrentAddressLocation) {
if (!CInfoSymSection.Entry)
return;

constexpr int WordSize = sizeof(uint32_t);
std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry;
const std::string &Metadata = CISI->Metadata;

// Emit the 4-byte length of the metadata.
W.write<uint32_t>(Metadata.size());

if (Metadata.size() == 0)
return;

// Write out the payload one word at a time.
size_t Index = 0;
while (Index + WordSize <= Metadata.size()) {
uint32_t NextWord =
llvm::support::endian::read32be(Metadata.data() + Index);
W.write<uint32_t>(NextWord);
Index += WordSize;
}

// If there is padding, we have at least one byte of payload left to emit.
if (CISI->paddingSize()) {
std::array<uint8_t, WordSize> LastWord = {0};
::memcpy(LastWord.data(), Metadata.data() + Index, Metadata.size() - Index);
W.write<uint32_t>(llvm::support::endian::read32be(LastWord.data()));
}

CurrentAddressLocation += CISI->size();
}

// Takes the log base 2 of the alignment and shifts the result into the 5 most
// significant bits of a byte, then or's in the csect type into the least
// significant 3 bits.
Expand Down
14 changes: 10 additions & 4 deletions llvm/test/CodeGen/PowerPC/aix-command-line-metadata.ll
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | \
; RUN: FileCheck --check-prefix=ASM %s

; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj < %s 2>&1 | \
; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s
; RUN: llvm-objdump --full-contents --section=.info %t.o | \
; RUN: FileCheck --check-prefix=OBJ %s
; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff -filetype=obj < %s 2>&1 | \
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -filetype=obj -o %t.o < %s
; RUN: llvm-objdump --full-contents --section=.info %t.o | \
; RUN: FileCheck --check-prefix=OBJ %s

; Verify that llvm.commandline metadata is emitted to .info sections and that the
; metadata is padded if necessary.

; OBJ: LLVM ERROR: emitXCOFFCInfoSym is not implemented yet on object generation path

; ASM: .info ".GCC.command.line", 0x0000003a,
; ASM: .info , 0x40282329, 0x6f707420, 0x636c616e, 0x67202d63, 0x6f6d6d61, 0x6e64202d
; ASM: .info , 0x6c696e65, 0x0a004028, 0x23296f70, 0x7420736f, 0x6d657468, 0x696e6720
; ASM: .info , 0x656c7365, 0x20313233, 0x0a000000

; OBJ: Contents of section .info:
; OBJ: 0000 0000003a 40282329 6f707420 636c616e ...:@(#)opt clan
; OBJ: 0010 67202d63 6f6d6d61 6e64202d 6c696e65 g -command -line
; OBJ: 0020 0a004028 23296f70 7420736f 6d657468 ..@(#)opt someth
; OBJ: 0030 696e6720 656c7365 20313233 0a000000 ing else 123....

!llvm.commandline = !{!0, !1}
!0 = !{!"clang -command -line"}
!1 = !{!"something else 123"}

0 comments on commit 311abf5

Please sign in to comment.