diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp --- a/llvm/lib/MC/MCSectionXCOFF.cpp +++ b/llvm/lib/MC/MCSectionXCOFF.cpp @@ -118,6 +118,10 @@ 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 --- a/llvm/lib/MC/XCOFFObjectWriter.cpp +++ b/llvm/lib/MC/XCOFFObjectWriter.cpp @@ -168,6 +168,24 @@ virtual ~CsectSectionEntry() {} }; +struct DwarfSectionEntry : public SectionEntry { + // For DWARF section entry. + std::unique_ptr DwarfSect; + + DwarfSectionEntry(StringRef N, int32_t Flags, + std::unique_ptr 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 @@ std::array Sections{ {&Text, &Data, &BSS, &TData, &TBSS}}; + std::vector DwarfSections; + CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); virtual void reset() override; @@ -231,12 +251,21 @@ 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 @@ // 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 @@ const auto *MCSec = cast(&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 DwarfSec = + std::make_unique(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 @@ : 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::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 @@ W.write(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(0); + // n_scnum + W.write(SectionIndex); + // n_type + W.write(0); + // n_sclass + W.write(XCOFF::C_DWARF); + // Always 1 aux entry for now. + W.write(1); + + // Now output the auxiliary entry. + // x_scnlen + W.write(DwarfSectionRef.Size); + // Reserved + W.write(0); + // x_nreloc. Set to 0 for now. + W.write(0); + // Reserved + W.write(0); + // Reserved + W.write(0); +} + void XCOFFObjectWriter::writeSymbolTableEntryForControlSection( const XCOFFSection &CSectionRef, int16_t SectionIndex, XCOFF::StorageClass StorageClass) { @@ -711,10 +765,10 @@ } 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 NameRef(Sec->Name, XCOFF::NameSize); @@ -722,8 +776,14 @@ // Write the Physical Address and Virtual Address. In an object file these // are the same. - W.write(Sec->Address); - W.write(Sec->Address); + // We use 0 for DWARF sections' Physical and Virtual Addresses. + if (!IsDwarf) { + W.write(Sec->Address); + W.write(Sec->Address); + } else { + W.write(0); + W.write(0); + } W.write(Sec->Size); W.write(Sec->FileOffsetToData); @@ -738,12 +798,25 @@ W.write(0); W.write(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(CSection.Address + Reloc.FixupOffsetInCsect); + const XCOFFSection &Section) { + if (Section.MCSec->isCsect()) + W.write(Section.Address + Reloc.FixupOffsetInCsect); + else { + // DWARF sections' address is set to 0. + assert(Section.MCSec->isDwarfSect() && "unsupport section type!"); + W.write(Reloc.FixupOffsetInCsect); + } W.write(Reloc.SymbolTableIndex); W.write(Reloc.SignAndSize); W.write(Reloc.Type); @@ -765,6 +838,10 @@ } } } + + 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 @@ } } } + + for (const auto &DwarfSection : DwarfSections) + writeSymbolTableEntryForDwarfSection(*DwarfSection.DwarfSect, + DwarfSection.Index); } void XCOFFObjectWriter::finalizeSectionInfo() { @@ -844,11 +925,17 @@ } } + 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 @@ 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 @@ 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 @@ 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 --- /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 --- 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 @@ ; 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