[llvm] 5f4c915 - [XCOFF] support DWARF for 32-bit XCOFF for object output
Chen Zheng via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 7 19:41:57 PDT 2021
Author: Chen Zheng
Date: 2021-10-08T02:35:11Z
New Revision: 5f4c91583ee772a6ce2c4f192e25b07e6075eb00
URL: https://github.com/llvm/llvm-project/commit/5f4c91583ee772a6ce2c4f192e25b07e6075eb00
DIFF: https://github.com/llvm/llvm-project/commit/5f4c91583ee772a6ce2c4f192e25b07e6075eb00.diff
LOG: [XCOFF] support DWARF for 32-bit XCOFF for object output
Reviewed By: jsji
Differential Revision: https://reviews.llvm.org/D97184
Added:
llvm/test/CodeGen/PowerPC/aix-dwarf.ll
Modified:
llvm/lib/MC/MCSectionXCOFF.cpp
llvm/lib/MC/XCOFFObjectWriter.cpp
llvm/test/DebugInfo/XCOFF/empty.ll
Removed:
################################################################################
diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp
index 648efc14da06c..7f7380bf810d9 100644
--- a/llvm/lib/MC/MCSectionXCOFF.cpp
+++ b/llvm/lib/MC/MCSectionXCOFF.cpp
@@ -118,6 +118,10 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
bool MCSectionXCOFF::UseCodeAlign() const { return getKind().isText(); }
bool MCSectionXCOFF::isVirtualSection() const {
- assert(isCsect() && "Only csect section can be virtual!");
+ // DWARF sections are always not virtual.
+ if (isDwarfSect())
+ return false;
+ assert(isCsect() &&
+ "Handling for isVirtualSection not implemented for this section!");
return XCOFF::XTY_CM == CsectProp->Type;
}
diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index adf0d3eb443c6..177253d7a9d76 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -168,6 +168,24 @@ struct CsectSectionEntry : public SectionEntry {
virtual ~CsectSectionEntry() {}
};
+struct DwarfSectionEntry : public SectionEntry {
+ // For DWARF section entry.
+ std::unique_ptr<XCOFFSection> DwarfSect;
+
+ DwarfSectionEntry(StringRef N, int32_t Flags,
+ std::unique_ptr<XCOFFSection> Sect)
+ : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)) {
+ assert(DwarfSect->MCSec->isDwarfSect() &&
+ "This should be a DWARF section!");
+ assert(N.size() <= XCOFF::NameSize && "section name too long");
+ memcpy(Name, N.data(), N.size());
+ }
+
+ DwarfSectionEntry(DwarfSectionEntry &&s) = default;
+
+ virtual ~DwarfSectionEntry() {}
+};
+
class XCOFFObjectWriter : public MCObjectWriter {
uint32_t SymbolTableEntryCount = 0;
@@ -213,6 +231,8 @@ class XCOFFObjectWriter : public MCObjectWriter {
std::array<CsectSectionEntry *const, 5> Sections{
{&Text, &Data, &BSS, &TData, &TBSS}};
+ std::vector<DwarfSectionEntry> DwarfSections;
+
CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
virtual void reset() override;
@@ -231,12 +251,21 @@ class XCOFFObjectWriter : public MCObjectWriter {
uint64_t);
void writeSymbolTableEntryForControlSection(const XCOFFSection &, int16_t,
XCOFF::StorageClass);
+ void writeSymbolTableEntryForDwarfSection(const XCOFFSection &, int16_t);
void writeFileHeader();
void writeSectionHeaderTable();
void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ void writeSectionForControlSectionEntry(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const CsectSectionEntry &CsectEntry,
+ uint32_t &CurrentAddressLocation);
+ void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const DwarfSectionEntry &DwarfEntry,
+ uint32_t &CurrentAddressLocation);
void writeSymbolTable(const MCAsmLayout &Layout);
void writeRelocations();
- void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &CSection);
+ void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);
// Called after all the csects and symbols have been processed by
// `executePostLayoutBinding`, this function handles building up the majority
@@ -290,6 +319,8 @@ void XCOFFObjectWriter::reset() {
// Reset any sections we have written to, and empty the section header table.
for (auto *Sec : Sections)
Sec->reset();
+ for (auto &DwarfSec : DwarfSections)
+ DwarfSec.reset();
// Reset states in XCOFFObjectWriter.
SymbolTableEntryCount = 0;
@@ -372,17 +403,32 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const auto *MCSec = cast<const MCSectionXCOFF>(&S);
assert(SectionMap.find(MCSec) == SectionMap.end() &&
"Cannot add a section twice.");
- assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
- "An undefined csect should not get registered.");
// If the name does not fit in the storage provided in the symbol table
// entry, add it to the string table.
if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
Strings.add(MCSec->getSymbolTableName());
-
- CsectGroup &Group = getCsectGroup(MCSec);
- Group.emplace_back(MCSec);
- SectionMap[MCSec] = &Group.back();
+ if (MCSec->isCsect()) {
+ // A new control section. Its CsectSectionEntry should already be staticly
+ // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
+ // the CsectSectionEntry.
+ assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
+ "An undefined csect should not get registered.");
+ CsectGroup &Group = getCsectGroup(MCSec);
+ Group.emplace_back(MCSec);
+ SectionMap[MCSec] = &Group.back();
+ } else if (MCSec->isDwarfSect()) {
+ // A new DwarfSectionEntry.
+ std::unique_ptr<XCOFFSection> DwarfSec =
+ std::make_unique<XCOFFSection>(MCSec);
+ SectionMap[MCSec] = DwarfSec.get();
+
+ DwarfSectionEntry SecEntry(MCSec->getName(),
+ MCSec->getDwarfSubtypeFlags().getValue(),
+ std::move(DwarfSec));
+ DwarfSections.push_back(std::move(SecEntry));
+ } else
+ llvm_unreachable("unsupport section type!");
}
for (const MCSymbol &S : Asm.symbols()) {
@@ -443,13 +489,20 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
: SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
};
- auto getVirtualAddress = [this,
- &Layout](const MCSymbol *Sym,
- const MCSectionXCOFF *ContainingCsect) {
- // If Sym is a csect, return csect's address.
- // If Sym is a label, return csect's address + label's offset from the csect.
- return SectionMap[ContainingCsect]->Address +
- (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0);
+ auto getVirtualAddress =
+ [this, &Layout](const MCSymbol *Sym,
+ const MCSectionXCOFF *ContainingSect) -> uint64_t {
+ // A DWARF section.
+ if (ContainingSect->isDwarfSect())
+ return Layout.getSymbolOffset(*Sym);
+
+ // A csect.
+ if (!Sym->isDefined())
+ return SectionMap[ContainingSect]->Address;
+
+ // A label.
+ assert(Sym->isDefined() && "not a valid object that has address!");
+ return SectionMap[ContainingSect]->Address + Layout.getSymbolOffset(*Sym);
};
const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
@@ -538,41 +591,12 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
const MCAsmLayout &Layout) {
uint32_t CurrentAddressLocation = 0;
- for (const auto *Section : Sections) {
- // Nothing to write for this Section.
- if (Section->Index == SectionEntry::UninitializedIndex ||
- Section->IsVirtual)
- continue;
-
- // There could be a gap (without corresponding zero padding) between
- // sections.
- assert(((CurrentAddressLocation <= Section->Address) ||
- (Section->Flags == XCOFF::STYP_TDATA) ||
- (Section->Flags == XCOFF::STYP_TBSS)) &&
- "CurrentAddressLocation should be less than or equal to section "
- "address if the section is not TData or TBSS.");
-
- CurrentAddressLocation = Section->Address;
-
- for (const auto *Group : Section->Groups) {
- for (const auto &Csect : *Group) {
- if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
- W.OS.write_zeros(PaddingSize);
- if (Csect.Size)
- Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
- CurrentAddressLocation = Csect.Address + Csect.Size;
- }
- }
-
- // 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 =
- Section->Address + Section->Size - CurrentAddressLocation) {
- W.OS.write_zeros(PaddingSize);
- CurrentAddressLocation += PaddingSize;
- }
- }
+ for (const auto *Section : Sections)
+ writeSectionForControlSectionEntry(Asm, Layout, *Section,
+ CurrentAddressLocation);
+ for (const auto &DwarfSection : DwarfSections)
+ writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection,
+ CurrentAddressLocation);
}
uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
@@ -654,6 +678,36 @@ void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
W.write<uint16_t>(0);
}
+void XCOFFObjectWriter::writeSymbolTableEntryForDwarfSection(
+ const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
+ assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");
+
+ // n_name, n_zeros, n_offset
+ writeSymbolName(DwarfSectionRef.getSymbolTableName());
+ // n_value
+ W.write<uint32_t>(0);
+ // n_scnum
+ W.write<int16_t>(SectionIndex);
+ // n_type
+ W.write<uint16_t>(0);
+ // n_sclass
+ W.write<uint8_t>(XCOFF::C_DWARF);
+ // Always 1 aux entry for now.
+ W.write<uint8_t>(1);
+
+ // Now output the auxiliary entry.
+ // x_scnlen
+ W.write<uint32_t>(DwarfSectionRef.Size);
+ // Reserved
+ W.write<uint32_t>(0);
+ // x_nreloc. Set to 0 for now.
+ W.write<uint32_t>(0);
+ // Reserved
+ W.write<uint32_t>(0);
+ // Reserved
+ W.write<uint16_t>(0);
+}
+
void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
const XCOFFSection &CSectionRef, int16_t SectionIndex,
XCOFF::StorageClass StorageClass) {
@@ -711,10 +765,10 @@ void XCOFFObjectWriter::writeFileHeader() {
}
void XCOFFObjectWriter::writeSectionHeaderTable() {
- for (const auto *Sec : Sections) {
+ auto writeSectionHeader = [&](const SectionEntry *Sec, bool IsDwarf) {
// Nothing to write for this Section.
if (Sec->Index == SectionEntry::UninitializedIndex)
- continue;
+ return false;
// Write Name.
ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
@@ -722,8 +776,14 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
// Write the Physical Address and Virtual Address. In an object file these
// are the same.
- W.write<uint32_t>(Sec->Address);
- W.write<uint32_t>(Sec->Address);
+ // We use 0 for DWARF sections' Physical and Virtual Addresses.
+ if (!IsDwarf) {
+ W.write<uint32_t>(Sec->Address);
+ W.write<uint32_t>(Sec->Address);
+ } else {
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+ }
W.write<uint32_t>(Sec->Size);
W.write<uint32_t>(Sec->FileOffsetToData);
@@ -738,12 +798,25 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
W.write<uint16_t>(0);
W.write<int32_t>(Sec->Flags);
- }
+
+ return true;
+ };
+
+ for (const auto *CsectSec : Sections)
+ writeSectionHeader(CsectSec, /* IsDwarf */ false);
+ for (const auto &DwarfSec : DwarfSections)
+ writeSectionHeader(&DwarfSec, /* IsDwarf */ true);
}
void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
- const XCOFFSection &CSection) {
- W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
+ const XCOFFSection &Section) {
+ if (Section.MCSec->isCsect())
+ W.write<uint32_t>(Section.Address + Reloc.FixupOffsetInCsect);
+ else {
+ // DWARF sections' address is set to 0.
+ assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
+ W.write<uint32_t>(Reloc.FixupOffsetInCsect);
+ }
W.write<uint32_t>(Reloc.SymbolTableIndex);
W.write<uint8_t>(Reloc.SignAndSize);
W.write<uint8_t>(Reloc.Type);
@@ -765,6 +838,10 @@ void XCOFFObjectWriter::writeRelocations() {
}
}
}
+
+ for (const auto &DwarfSection : DwarfSections)
+ for (const auto &Reloc : DwarfSection.DwarfSect->Relocations)
+ writeRelocation(Reloc, *DwarfSection.DwarfSect);
}
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
@@ -819,6 +896,10 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
}
}
}
+
+ for (const auto &DwarfSection : DwarfSections)
+ writeSymbolTableEntryForDwarfSection(*DwarfSection.DwarfSect,
+ DwarfSection.Index);
}
void XCOFFObjectWriter::finalizeSectionInfo() {
@@ -844,11 +925,17 @@ void XCOFFObjectWriter::finalizeSectionInfo() {
}
}
+ for (auto &DwarfSection : DwarfSections)
+ DwarfSection.RelocationCount = DwarfSection.DwarfSect->Relocations.size();
+
// Calculate the file offset to the relocation entries.
uint64_t RawPointer = RelocationEntryOffset;
- for (auto Sec : Sections) {
- if (Sec->Index == SectionEntry::UninitializedIndex || !Sec->RelocationCount)
- continue;
+ auto calcOffsetToRelocations = [&](SectionEntry *Sec, bool IsDwarf) {
+ if (!IsDwarf && Sec->Index == SectionEntry::UninitializedIndex)
+ return false;
+
+ if (!Sec->RelocationCount)
+ return false;
Sec->FileOffsetToRelocations = RawPointer;
const uint32_t RelocationSizeInSec =
@@ -856,7 +943,15 @@ void XCOFFObjectWriter::finalizeSectionInfo() {
RawPointer += RelocationSizeInSec;
if (RawPointer > UINT32_MAX)
report_fatal_error("Relocation data overflowed this object file.");
- }
+
+ return true;
+ };
+
+ for (auto *Sec : Sections)
+ calcOffsetToRelocations(Sec, /* IsDwarf */ false);
+
+ for (auto &DwarfSec : DwarfSections)
+ calcOffsetToRelocations(&DwarfSec, /* IsDwarf */ true);
// TODO Error check that the number of symbol table entries fits in 32-bits
// signed ...
@@ -944,6 +1039,37 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
Section->Size = Address - Section->Address;
}
+ for (auto &DwarfSection : DwarfSections) {
+ assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");
+
+ XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
+ const MCSectionXCOFF *MCSec = DwarfSect.MCSec;
+
+ // Section index.
+ DwarfSection.Index = SectionIndex++;
+ SectionCount++;
+
+ // Symbol index.
+ DwarfSect.SymbolTableIndex = SymbolTableIndex;
+ SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for the csect.
+ SymbolTableIndex += 2;
+
+ // Section address. Make it align to section alignment.
+ // We use address 0 for DWARF sections' Physical and Virtual Addresses.
+ // This address is used to tell where is the section in the final object.
+ // See writeSectionForDwarfSectionEntry().
+ DwarfSection.Address = DwarfSect.Address =
+ alignTo(Address, MCSec->getAlignment());
+
+ // Section size.
+ // For DWARF section, we must use the real size which may be not aligned.
+ DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec);
+
+ // Make the Address align to default alignment for follow section.
+ Address = alignTo(DwarfSect.Address + DwarfSect.Size, DefaultSectionAlign);
+ }
+
SymbolTableEntryCount = SymbolTableIndex;
// Calculate the RawPointer value for each section.
@@ -959,9 +1085,102 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
report_fatal_error("Section raw data overflowed this object file.");
}
+ for (auto &DwarfSection : DwarfSections) {
+ // Address of csect sections are always aligned to DefaultSectionAlign, but
+ // address of DWARF section are aligned to Section alignment which may be
+ // bigger than DefaultSectionAlign, need to execlude the padding bits.
+ RawPointer =
+ alignTo(RawPointer, DwarfSection.DwarfSect->MCSec->getAlignment());
+
+ DwarfSection.FileOffsetToData = RawPointer;
+ // Some section entries, like DWARF section size is not aligned, so
+ // RawPointer may be not aligned.
+ RawPointer += DwarfSection.Size;
+ // Make sure RawPointer is aligned.
+ RawPointer = alignTo(RawPointer, DefaultSectionAlign);
+
+ assert(RawPointer <= UINT32_MAX &&
+ "Section raw data overflowed this object file.");
+ }
+
RelocationEntryOffset = RawPointer;
}
+void XCOFFObjectWriter::writeSectionForControlSectionEntry(
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const CsectSectionEntry &CsectEntry, uint32_t &CurrentAddressLocation) {
+ // Nothing to write for this Section.
+ if (CsectEntry.Index == SectionEntry::UninitializedIndex)
+ return;
+
+ // There could be a gap (without corresponding zero padding) between
+ // sections.
+ // There could be a gap (without corresponding zero padding) between
+ // sections.
+ assert(((CurrentAddressLocation <= CsectEntry.Address) ||
+ (CsectEntry.Flags == XCOFF::STYP_TDATA) ||
+ (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&
+ "CurrentAddressLocation should be less than or equal to section "
+ "address if the section is not TData or TBSS.");
+
+ CurrentAddressLocation = CsectEntry.Address;
+
+ // For virtual sections, nothing to write. But need to increase
+ // CurrentAddressLocation for later sections like DWARF section has a correct
+ // writing location.
+ if (CsectEntry.IsVirtual) {
+ CurrentAddressLocation += CsectEntry.Size;
+ return;
+ }
+
+ for (const auto &Group : CsectEntry.Groups) {
+ for (const auto &Csect : *Group) {
+ if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
+ W.OS.write_zeros(PaddingSize);
+ if (Csect.Size)
+ Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
+ CurrentAddressLocation = Csect.Address + Csect.Size;
+ }
+ }
+
+ // 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 =
+ CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
+ W.OS.write_zeros(PaddingSize);
+ CurrentAddressLocation += PaddingSize;
+ }
+}
+
+void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const DwarfSectionEntry &DwarfEntry, uint32_t &CurrentAddressLocation) {
+ // There could be a gap (without corresponding zero padding) between
+ // sections. For example DWARF section alignment is bigger than
+ // DefaultSectionAlign.
+ assert(CurrentAddressLocation <= DwarfEntry.Address &&
+ "CurrentAddressLocation should be less than or equal to section "
+ "address.");
+
+ if (uint32_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
+ W.OS.write_zeros(PaddingSize);
+
+ if (DwarfEntry.Size)
+ Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout);
+
+ CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
+
+ // DWARF section size is not aligned to DefaultSectionAlign.
+ // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
+ uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
+ uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0;
+ if (TailPaddingSize)
+ W.OS.write_zeros(TailPaddingSize);
+
+ CurrentAddressLocation += TailPaddingSize;
+}
+
// 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.
diff --git a/llvm/test/CodeGen/PowerPC/aix-dwarf.ll b/llvm/test/CodeGen/PowerPC/aix-dwarf.ll
new file mode 100644
index 0000000000000..263cbc668a90b
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-dwarf.ll
@@ -0,0 +1,117 @@
+
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s
+; RUN: llvm-readobj --section-headers %t.o | FileCheck %s --check-prefix=SEC
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s
+; RUN: llvm-objdump -r %t.o | FileCheck %s --check-prefix=RELO
+
+; This file is copied from test/DebugInfo/XCOFF/empty.ll.
+; In this test, we focus on XCOFF related formats, like section headers,
+; relocation entries.
+
+source_filename = "1.c"
+target datalayout = "E-m:a-p:32:32-i64:64-n32"
+
+; Function Attrs: noinline nounwind optnone
+define i32 @main() #0 !dbg !8 {
+entry:
+ %retval = alloca i32, align 4
+ store i32 0, i32* %retval, align 4
+ ret i32 0, !dbg !12
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "1.c", directory: "debug")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 2}
+!6 = !{i32 7, !"PIC Level", i32 2}
+!7 = !{!"clang version 12.0.0"}
+!8 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !9, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !DILocation(line: 3, column: 3, scope: !8)
+
+; SEC: AddressSize: 32bit
+; SEC-NEXT: Sections [
+; SEC-NEXT: Section {
+; SEC-NEXT: Index: 1
+; SEC-NEXT: Name: .text
+; SEC-NEXT: PhysicalAddress: 0x0
+; SEC-NEXT: VirtualAddress: 0x0
+; SEC-NEXT: Size: 0x28
+; SEC-NEXT: RawDataOffset: 0xDC
+; SEC-NEXT: RelocationPointer: 0x0
+; SEC-NEXT: LineNumberPointer: 0x0
+; SEC-NEXT: NumberOfRelocations: 0
+; SEC-NEXT: NumberOfLineNumbers: 0
+; SEC-NEXT: Type: STYP_TEXT (0x20)
+; SEC-NEXT: }
+; SEC-NEXT: Section {
+; SEC-NEXT: Index: 2
+; SEC-NEXT: Name: .data
+; SEC-NEXT: PhysicalAddress: 0x28
+; SEC-NEXT: VirtualAddress: 0x28
+; SEC-NEXT: Size: 0xC
+; SEC-NEXT: RawDataOffset: 0x104
+; SEC-NEXT: RelocationPointer: 0x1D8
+; SEC-NEXT: LineNumberPointer: 0x0
+; SEC-NEXT: NumberOfRelocations: 2
+; SEC-NEXT: NumberOfLineNumbers: 0
+; SEC-NEXT: Type: STYP_DATA (0x40)
+; SEC-NEXT: }
+; SEC-NEXT: Section {
+; SEC-NEXT: Index: 3
+; SEC-NEXT: Name: .dwabrev
+; SEC-NEXT: PhysicalAddress: 0x0
+; SEC-NEXT: VirtualAddress: 0x0
+; SEC-NEXT: Size: 0x36
+; SEC-NEXT: RawDataOffset: 0x110
+; SEC-NEXT: RelocationPointer: 0x0
+; SEC-NEXT: LineNumberPointer: 0x0
+; SEC-NEXT: NumberOfRelocations: 0
+; SEC-NEXT: NumberOfLineNumbers: 0
+; SEC-NEXT: Type: STYP_DWARF (0x10)
+; SEC-NEXT: }
+; SEC-NEXT: Section {
+; SEC-NEXT: Index: 4
+; SEC-NEXT: Name: .dwinfo
+; SEC-NEXT: PhysicalAddress: 0x0
+; SEC-NEXT: VirtualAddress: 0x0
+; SEC-NEXT: Size: 0x57
+; SEC-NEXT: RawDataOffset: 0x148
+; SEC-NEXT: RelocationPointer: 0x1EC
+; SEC-NEXT: LineNumberPointer: 0x0
+; SEC-NEXT: NumberOfRelocations: 4
+; SEC-NEXT: NumberOfLineNumbers: 0
+; SEC-NEXT: Type: STYP_DWARF (0x10)
+; SEC-NEXT: }
+; SEC-NEXT: Section {
+; SEC-NEXT: Index: 5
+; SEC-NEXT: Name: .dwline
+; SEC-NEXT: PhysicalAddress: 0x0
+; SEC-NEXT: VirtualAddress: 0x0
+; SEC-NEXT: Size: 0x36
+; SEC-NEXT: RawDataOffset: 0x1A0
+; SEC-NEXT: RelocationPointer: 0x214
+; SEC-NEXT: LineNumberPointer: 0x0
+; SEC-NEXT: NumberOfRelocations: 1
+; SEC-NEXT: NumberOfLineNumbers: 0
+; SEC-NEXT: Type: STYP_DWARF (0x10)
+; SEC-NEXT: }
+; SEC-NEXT: ]
+
+; RELO: RELOCATION RECORDS FOR [.dwinfo]:
+; RELO-NEXT: OFFSET TYPE VALUE
+; RELO-NEXT: 00000006 R_POS .dwabrev
+; RELO-NEXT: 00000027 R_POS .dwline
+; RELO-NEXT: 00000009 R_POS .text
+; RELO-NEXT: 0000003a R_POS .text
+; RELO: RELOCATION RECORDS FOR [.dwline]:
+; RELO-NEXT: OFFSET TYPE VALUE
+; RELO-NEXT: 00000000 R_POS .text
diff --git a/llvm/test/DebugInfo/XCOFF/empty.ll b/llvm/test/DebugInfo/XCOFF/empty.ll
index 67745c0a4c3a8..d1ee6b68e38aa 100644
--- a/llvm/test/DebugInfo/XCOFF/empty.ll
+++ b/llvm/test/DebugInfo/XCOFF/empty.ll
@@ -3,6 +3,8 @@
; RUN: FileCheck %s --check-prefix=ASM32
; RUN: llc -debugger-tune=gdb -mtriple powerpc64-ibm-aix-xcoff < %s | \
; RUN: FileCheck %s --check-prefix=ASM64
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj < %s | \
+; RUN: llvm-dwarfdump --all - | FileCheck %s --check-prefix=DWARF32
source_filename = "1.c"
target datalayout = "E-m:a-p:32:32-i64:64-n32"
@@ -434,3 +436,89 @@ entry:
; ASM64-NEXT: .byte 1
; ASM64-NEXT: .byte 1
; ASM64-NEXT: L..debug_line_end0:
+
+; DWARF32: : file format aixcoff-rs6000
+; DWARF32: .debug_abbrev contents:
+; DWARF32-NEXT: Abbrev table for offset: 0x00000000
+; DWARF32-NEXT: [1] DW_TAG_compile_unit DW_CHILDREN_yes
+; DWARF32-NEXT: DW_AT_producer DW_FORM_string
+; DWARF32-NEXT: DW_AT_language DW_FORM_data2
+; DWARF32-NEXT: DW_AT_name DW_FORM_string
+; DWARF32-NEXT: DW_AT_stmt_list DW_FORM_sec_offset
+; DWARF32-NEXT: DW_AT_comp_dir DW_FORM_string
+; DWARF32-NEXT: DW_AT_low_pc DW_FORM_addr
+; DWARF32-NEXT: DW_AT_high_pc DW_FORM_data4
+; DWARF32: [2] DW_TAG_subprogram DW_CHILDREN_no
+; DWARF32-NEXT: DW_AT_low_pc DW_FORM_addr
+; DWARF32-NEXT: DW_AT_high_pc DW_FORM_data4
+; DWARF32-NEXT: DW_AT_frame_base DW_FORM_exprloc
+; DWARF32-NEXT: DW_AT_name DW_FORM_string
+; DWARF32-NEXT: DW_AT_decl_file DW_FORM_data1
+; DWARF32-NEXT: DW_AT_decl_line DW_FORM_data1
+; DWARF32-NEXT: DW_AT_prototyped DW_FORM_flag_present
+; DWARF32-NEXT: DW_AT_type DW_FORM_ref4
+; DWARF32-NEXT: DW_AT_external DW_FORM_flag_present
+; DWARF32: [3] DW_TAG_base_type DW_CHILDREN_no
+; DWARF32-NEXT: DW_AT_name DW_FORM_string
+; DWARF32-NEXT: DW_AT_encoding DW_FORM_data1
+; DWARF32-NEXT: DW_AT_byte_size DW_FORM_data1
+; DWARF32: .debug_info contents:
+; DWARF32-NEXT: 0x00000000: Compile Unit: length = 0x00000053, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x04 (next unit at 0x00000057)
+; DWARF32: 0x0000000b: DW_TAG_compile_unit
+; DWARF32-NEXT: DW_AT_producer ("clang version 12.0.0")
+; DWARF32-NEXT: DW_AT_language (DW_LANG_C99)
+; DWARF32-NEXT: DW_AT_name ("1.c")
+; DWARF32-NEXT: DW_AT_stmt_list (0x00000000)
+; DWARF32-NEXT: DW_AT_comp_dir ("debug")
+; DWARF32-NEXT: DW_AT_low_pc (0x00000000)
+; DWARF32-NEXT: DW_AT_high_pc (0x00000026)
+; DWARF32: 0x00000039: DW_TAG_subprogram
+; DWARF32-NEXT: DW_AT_low_pc (0x00000000)
+; DWARF32-NEXT: DW_AT_high_pc (0x00000026)
+; DWARF32-NEXT: DW_AT_frame_base (DW_OP_reg1 R1)
+; DWARF32-NEXT: DW_AT_name ("main")
+; DWARF32-NEXT: DW_AT_decl_file ("debug/1.c")
+; DWARF32-NEXT: DW_AT_decl_line (1)
+; DWARF32-NEXT: DW_AT_prototyped (true)
+; DWARF32-NEXT: DW_AT_type (0x0000004f "int")
+; DWARF32-NEXT: DW_AT_external (true)
+; DWARF32: 0x0000004f: DW_TAG_base_type
+; DWARF32-NEXT: DW_AT_name ("int")
+; DWARF32-NEXT: DW_AT_encoding (DW_ATE_signed)
+; DWARF32-NEXT: DW_AT_byte_size (0x04)
+; DWARF32: 0x00000056: NULL
+; DWARF32: .debug_line contents:
+; DWARF32-NEXT: debug_line[0x00000000]
+; DWARF32-NEXT: Line table prologue:
+; DWARF32-NEXT: total_length: 0x00000032
+; DWARF32-NEXT: format: DWARF32
+; DWARF32-NEXT: version: 4
+; DWARF32-NEXT: prologue_length: 0x0000001b
+; DWARF32-NEXT: min_inst_length: 4
+; DWARF32-NEXT: max_ops_per_inst: 1
+; DWARF32-NEXT: default_is_stmt: 1
+; DWARF32-NEXT: line_base: -5
+; DWARF32-NEXT: line_range: 14
+; DWARF32-NEXT: opcode_base: 13
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_copy] = 0
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_advance_pc] = 1
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_advance_line] = 1
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_set_file] = 1
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_set_column] = 1
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_negate_stmt] = 0
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_set_basic_block] = 0
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_const_add_pc] = 0
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_set_prologue_end] = 0
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
+; DWARF32-NEXT: standard_opcode_lengths[DW_LNS_set_isa] = 1
+; DWARF32-NEXT: file_names[ 1]:
+; DWARF32-NEXT: name: "1.c"
+; DWARF32-NEXT: dir_index: 0
+; DWARF32-NEXT: mod_time: 0x00000000
+; DWARF32-NEXT: length: 0x00000000
+; DWARF32: Address Line Column File ISA Discriminator Flags
+; DWARF32-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
+; DWARF32-NEXT: 0x0000000000000000 2 0 1 0 0 is_stmt
+; DWARF32-NEXT: 0x0000000000000004 3 3 1 0 0 is_stmt prologue_end
+; DWARF32-NEXT: 0x0000000000000024 3 3 1 0 0 is_stmt end_sequence
More information about the llvm-commits
mailing list