[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