diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h --- a/llvm/include/llvm/BinaryFormat/XCOFF.h +++ b/llvm/include/llvm/BinaryFormat/XCOFF.h @@ -37,6 +37,8 @@ constexpr size_t SymbolTableEntrySize = 18; constexpr size_t RelocationSerializationSize32 = 10; constexpr size_t RelocationSerializationSize64 = 14; +constexpr size_t ExceptionSectionEntrySize32 = 6; +constexpr size_t ExceptionSectionEntrySize64 = 10; constexpr uint16_t RelocOverflow = 65535; constexpr uint8_t AllocRegNo = 31; diff --git a/llvm/include/llvm/MC/MCObjectWriter.h b/llvm/include/llvm/MC/MCObjectWriter.h --- a/llvm/include/llvm/MC/MCObjectWriter.h +++ b/llvm/include/llvm/MC/MCObjectWriter.h @@ -105,6 +105,11 @@ std::vector &getAddrsigSyms() { return AddrsigSyms; } + virtual void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap, + unsigned LanguageCode, unsigned ReasonCode, + unsigned FunctionSize, bool hasDebug) { + report_fatal_error("addExceptionEntry 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 diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -634,7 +634,8 @@ /// \param Symbol - The function containing the trap. /// \param Lang - The language code for the exception entry. /// \param Reason - The reason code for the exception entry. - virtual void emitXCOFFExceptDirective(const MCSymbol *Symbol, MCSymbol *Trap, + virtual void emitXCOFFExceptDirective(const MCSymbol *Symbol, + const MCSymbol *Trap, unsigned Lang, unsigned Reason, unsigned FunctionSize, bool hasDebug); diff --git a/llvm/include/llvm/MC/MCXCOFFStreamer.h b/llvm/include/llvm/MC/MCXCOFFStreamer.h --- a/llvm/include/llvm/MC/MCXCOFFStreamer.h +++ b/llvm/include/llvm/MC/MCXCOFFStreamer.h @@ -41,7 +41,7 @@ report_fatal_error("emitXCOFFRenameDirective is not implemented yet on " "object generation path"); } - void emitXCOFFExceptDirective(const MCSymbol *Symbol, MCSymbol *Trap, + void emitXCOFFExceptDirective(const MCSymbol *Symbol, const MCSymbol *Trap, unsigned Lang, unsigned Reason, unsigned FunctionSize, bool hasDebug) override; }; diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -197,7 +197,8 @@ void emitXCOFFRefDirective(StringRef Name) override; - void emitXCOFFExceptDirective(const MCSymbol *Symbol, MCSymbol *Trap, + void emitXCOFFExceptDirective(const MCSymbol *Symbol, + const MCSymbol *Trap, unsigned Lang, unsigned Reason, unsigned FunctionSize, bool hasDebug) override; @@ -947,7 +948,8 @@ } void MCAsmStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, - MCSymbol *Trap, unsigned Lang, + const MCSymbol *Trap, + unsigned Lang, unsigned Reason, unsigned FunctionSize, bool hasDebug) { diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1191,8 +1191,8 @@ } void MCStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, - MCSymbol *Trap, unsigned Lang, - unsigned Reason, + const MCSymbol *Trap, + unsigned Lang, unsigned Reason, unsigned FunctionSize, bool hasDebug) { report_fatal_error("emitXCOFFExceptDirective is only supported on " diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp --- a/llvm/lib/MC/MCXCOFFStreamer.cpp +++ b/llvm/lib/MC/MCXCOFFStreamer.cpp @@ -82,13 +82,12 @@ } void MCXCOFFStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, - MCSymbol *Trap, unsigned Lang, - unsigned Reason, + const MCSymbol *Trap, + unsigned Lang, unsigned Reason, unsigned FunctionSize, bool hasDebug) { - report_fatal_error( - "emitXCOFFExceptDirective not yet supported for integrated " - "assembler path."); + getAssembler().getWriter().addExceptionEntry(Symbol, Trap, Lang, Reason, + FunctionSize, hasDebug); } void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 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 @@ -28,6 +28,7 @@ #include "llvm/Support/MathExtras.h" #include +#include using namespace llvm; @@ -199,6 +200,34 @@ virtual ~DwarfSectionEntry() = default; }; +struct ExceptionTableEntry { + const MCSymbol *Trap; + uint64_t TrapAddress; + unsigned Lang; + unsigned Reason; + + ExceptionTableEntry(const MCSymbol *Trap, unsigned Lang, unsigned Reason) : + Trap(Trap), Lang(Lang), Reason(Reason) {} +}; + +struct ExceptionInfo { + unsigned FunctionSize; + std::vector Entries; +}; + +struct ExceptionSectionEntry : public SectionEntry { + std::map ExceptionTable; + bool isDebugEnabled; + + ExceptionSectionEntry(StringRef N, int32_t Flags) : + SectionEntry(N, Flags | XCOFF::STYP_EXCEPT) { + assert(N.size() <= XCOFF::NameSize && "Section too long."); + memcpy(Name, N.data(), N.size()); + } + + virtual ~ExceptionSectionEntry() = default; +}; + class XCOFFObjectWriter : public MCObjectWriter { uint32_t SymbolTableEntryCount = 0; @@ -251,6 +280,8 @@ std::vector DwarfSections; + ExceptionSectionEntry ExceptionSection; + CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); void reset() override; @@ -287,12 +318,22 @@ const MCAsmLayout &Layout, const DwarfSectionEntry &DwarfEntry, uint64_t &CurrentAddressLocation); + void writeSectionForExceptionSectionEntry(const MCAssembler &Asm, + const MCAsmLayout &Layout, + ExceptionSectionEntry &ExceptionEntry, + uint64_t &CurrentAddressLocation); void writeSymbolTable(const MCAsmLayout &Layout); void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion, uint64_t NumberOfRelocEnt = 0); void writeSymbolAuxCsectEntry(uint64_t SectionOrLength, uint8_t SymbolAlignmentAndType, uint8_t StorageMappingClass); + void writeSymbolAuxFunctionEntry(uint32_t EntryOffset, + uint32_t FunctionSize, + uint64_t LineNumberPointer, + uint32_t EndIndex); + void writeSymbolAuxExceptionEntry(uint64_t EntryOffset, + uint32_t FunctionSize, uint32_t EndIndex); void writeSymbolEntry(StringRef SymbolName, uint64_t Value, int16_t SectionNumber, uint16_t SymbolType, uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1); @@ -309,6 +350,14 @@ // `Sections`. void assignAddressesAndIndices(const MCAsmLayout &); void finalizeSectionInfo(); + void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap, + unsigned LanguageCode, unsigned ReasonCode, + unsigned FunctionSize, bool hasDebug) override; + bool hasExceptionSection() { + return !ExceptionSection.ExceptionTable.empty(); + } + unsigned getExceptionSectionSize(); + unsigned getExceptionOffset(const MCSymbol *Symbol); size_t auxiliaryHeaderSize() const { // 64-bit object files have no auxiliary header. @@ -337,7 +386,8 @@ TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false, CsectGroups{&TDataCsects}), TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true, - CsectGroups{&TBSSCsects}) {} + CsectGroups{&TBSSCsects}), + ExceptionSection(".except", XCOFF::STYP_EXCEPT) {} void XCOFFObjectWriter::reset() { // Clear the mappings we created. @@ -350,6 +400,7 @@ Sec->reset(); for (auto &DwarfSec : DwarfSections) DwarfSec.reset(); + ExceptionSection.reset(); // Reset states in XCOFFObjectWriter. SymbolTableEntryCount = 0; @@ -634,6 +685,8 @@ for (const auto &DwarfSection : DwarfSections) writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection, CurrentAddressLocation); + writeSectionForExceptionSectionEntry(Asm, Layout, ExceptionSection, + CurrentAddressLocation); } uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, @@ -689,8 +742,6 @@ W.write(Value); } W.write(SectionNumber); - // TODO Set the function indicator (bit 10, 0x0020) for functions - // when debugging is enabled. W.write(SymbolType); W.write(StorageClass); W.write(NumberOfAuxEntries); @@ -734,10 +785,38 @@ assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address && "Symbol address overflowed."); - writeSymbolEntry(SymbolRef.getSymbolTableName(), - CSectionRef.Address + SymbolOffset, SectionIndex, - SymbolRef.getVisibilityType(), SymbolRef.getStorageClass()); - + auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym); + if (Entry != ExceptionSection.ExceptionTable.end()) { + writeSymbolEntry(SymbolRef.getSymbolTableName(), + CSectionRef.Address + SymbolOffset, SectionIndex, + // In the old version of the 32-bit XCOFF interpretation, + // symbols may require bit 10 (0x0020) to be set if the + // symbol is a function, otherwise the bit should be 0. + is64Bit() ? SymbolRef.getVisibilityType() + : SymbolRef.getVisibilityType() | 0x0020, + SymbolRef.getStorageClass(), + (is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2); + if (is64Bit() && ExceptionSection.isDebugEnabled) { + // On 64 bit with debugging enabled, we have a csect, exception, and + // function auxilliary entries, so we must increment symbol index by 4. + writeSymbolAuxExceptionEntry( + ExceptionSection.FileOffsetToData + getExceptionOffset(Entry->first), + Entry->second.FunctionSize, SymbolIndexMap[Entry->first] + 4); + } + // For exception section entries, csect and function auxilliary entries + // must exist. On 64-bit there is also an exception auxilliary entry. + writeSymbolAuxFunctionEntry(ExceptionSection.FileOffsetToData + + getExceptionOffset(Entry->first), + Entry->second.FunctionSize, 0, + (is64Bit() && ExceptionSection.isDebugEnabled) + ? SymbolIndexMap[Entry->first] + 4 + : SymbolIndexMap[Entry->first] + 3); + } else { + writeSymbolEntry(SymbolRef.getSymbolTableName(), + CSectionRef.Address + SymbolOffset, SectionIndex, + SymbolRef.getVisibilityType(), + SymbolRef.getStorageClass()); + } writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD, CSectionRef.MCSec->getMappingClass()); } @@ -762,6 +841,37 @@ CSectionRef.MCSec->getMappingClass()); } +void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset, + uint32_t FunctionSize, + uint64_t LineNumberPointer, + uint32_t EndIndex) { + if (is64Bit()) + writeWord(LineNumberPointer); + else + W.write(EntryOffset); + W.write(FunctionSize); + if (!is64Bit()) + writeWord(LineNumberPointer); + W.write(EndIndex); + if (is64Bit()) { + W.OS.write_zeros(1); + W.write(XCOFF::AUX_FCN); + } else { + W.OS.write_zeros(2); + } +} + +void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset, + uint32_t FunctionSize, + uint32_t EndIndex) { + assert(is64Bit() && "Exception auxilliary entries are 64-bit only."); + W.write(EntryOffset); + W.write(FunctionSize); + W.write(EndIndex); + W.OS.write_zeros(1); // Pad (unused) + W.write(XCOFF::AUX_EXCEPT); +} + void XCOFFObjectWriter::writeFileHeader() { W.write(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32); W.write(SectionCount); @@ -833,6 +943,8 @@ writeSectionHeader(CsectSec, /* IsDwarf */ false); for (const auto &DwarfSec : DwarfSections) writeSectionHeader(&DwarfSec, /* IsDwarf */ true); + if (hasExceptionSection()) + writeSectionHeader(&ExceptionSection, false); } void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc, @@ -974,6 +1086,55 @@ SymbolTableOffset = RawPointer; } +void XCOFFObjectWriter::addExceptionEntry(const MCSymbol *Symbol, + const MCSymbol *Trap, + unsigned LanguageCode, + unsigned ReasonCode, + unsigned FunctionSize, + bool hasDebug) { + // If a module had debug info, debugging is enabled and XCOFF emits the + // exception auxilliary entry. + if (hasDebug) + ExceptionSection.isDebugEnabled = true; + auto Entry = ExceptionSection.ExceptionTable.find(Symbol); + if (Entry != ExceptionSection.ExceptionTable.end()) { + Entry->second.Entries.push_back( + ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); + return; + } + ExceptionInfo NewEntry; + NewEntry.FunctionSize = FunctionSize; + NewEntry.Entries.push_back( + ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); + ExceptionSection.ExceptionTable.insert( + std::pair(Symbol, NewEntry)); +} + +unsigned XCOFFObjectWriter::getExceptionSectionSize() { + unsigned EntryNum=0; + + for (auto it = ExceptionSection.ExceptionTable.begin(); + it != ExceptionSection.ExceptionTable.end(); ++it) + // The size() gets +1 to account for the initial entry containing the + // symbol table index. + EntryNum += it->second.Entries.size() + 1; + + return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64 : + XCOFF::ExceptionSectionEntrySize32); +} + +unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol *Symbol) { + unsigned EntryNum = 0; + for (auto it = ExceptionSection.ExceptionTable.begin(); + it != ExceptionSection.ExceptionTable.end(); ++it) { + if (Symbol == it->first) + break; + EntryNum += it->second.Entries.size() + 1; + } + return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64 : + XCOFF::ExceptionSectionEntrySize32); +} + void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) { // The symbol table starts with all the C_FILE symbols. uint32_t SymbolTableIndex = FileNames.size(); @@ -1035,11 +1196,28 @@ SymbolTableIndex += 2; for (auto &Sym : Csect.Syms) { + bool hasExceptEntry = false; + auto Entry = ExceptionSection.ExceptionTable.find(Sym.MCSym); + if(Entry != ExceptionSection.ExceptionTable.end()) { + hasExceptEntry = true; + for (auto &TrapEntry : Entry->second.Entries) { + TrapEntry.TrapAddress = Layout.getSymbolOffset(*(Sym.MCSym)) + + TrapEntry.Trap->getOffset(); + } + } Sym.SymbolTableIndex = SymbolTableIndex; SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex; // 1 main and 1 auxiliary symbol table entry for each contained - // symbol. + // symbol. For symbols with exception section entries, a function + // auxilliary entry is needed, and on 64-bit XCOFF with debugging + // enabled, an additional exception auxilliary entry is needed. SymbolTableIndex += 2; + if (hasExceptionSection() && hasExceptEntry) { + if (is64Bit() && ExceptionSection.isDebugEnabled) + SymbolTableIndex += 2; + else + SymbolTableIndex += 1; + } } } @@ -1109,7 +1287,14 @@ DefaultSectionAlign); LastDwarfSection->MemorySize = Address - LastDwarfSection->Address; } - + if (hasExceptionSection()) { + ExceptionSection.Index = SectionIndex++; + SectionCount++; + ExceptionSection.Address = 0; + ExceptionSection.Size = getExceptionSectionSize(); + Address += ExceptionSection.Size; + Address = alignTo(Address, DefaultSectionAlign); + } SymbolTableEntryCount = SymbolTableIndex; // Calculate the RawPointer value for each section. @@ -1144,6 +1329,14 @@ "Section raw data overflowed this object file."); } + if (hasExceptionSection()) { + ExceptionSection.FileOffsetToData = RawPointer; + RawPointer += ExceptionSection.Size; + + assert(RawPointer <= MaxRawDataSize && + "Section raw data overflowed this object file."); + } + RelocationEntryOffset = RawPointer; } @@ -1222,6 +1415,29 @@ CurrentAddressLocation += TailPaddingSize; } +void XCOFFObjectWriter::writeSectionForExceptionSectionEntry( + const MCAssembler &Asm, const MCAsmLayout &Layout, + ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation) { + for (auto it = ExceptionEntry.ExceptionTable.begin(); + it != ExceptionEntry.ExceptionTable.end(); it++) { + // For every symbol that has exception entries, you must start the entries + // with an initial symbol table index entry + W.write(SymbolIndexMap[it->first]); + if (is64Bit()) { + // 4-byte padding on 64-bit. + W.OS.write_zeros(4); + } + W.OS.write_zeros(2); + for (auto &TrapEntry : it->second.Entries) { + writeWord(TrapEntry.TrapAddress); + W.write(TrapEntry.Lang); + W.write(TrapEntry.Reason); + } + } + + CurrentAddressLocation += getExceptionSectionSize(); +} + // 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-xcoff-exception-section-debug.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section-debug.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section-debug.ll @@ -0,0 +1,151 @@ +; This file contains exception section testing for when debug information is present. +; The 32-bit test should not print exception auxilliary entries because they are a 64-bit only feature. +; Exception auxilliary entries are present in the 64-bit tests because 64-bit && debug enabled are the requirements. +; RUN: llc -mtriple=powerpc-ibm-aix-xcoff -filetype=obj -o %t_32.o < %s +; RUN: llvm-readobj --syms %t_32.o | FileCheck %s --check-prefix=SYMS32 +; RUN: llc -mtriple=powerpc64-unknown-aix -filetype=obj -o %t_32.o < %s +; RUN: llvm-readobj --syms %t_32.o | FileCheck %s --check-prefix=SYMS64 + +; If any debug information is included in a module and is XCOFF64, exception auxilliary entries are emitted + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} + +!0 = !{i32 2, !"Dwarf Version", i32 3} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "ASTI IR translator", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false) +!3 = !DIFile(filename: "t.f", directory: ".") +!4 = distinct !DISubprogram(name: "test__trap_annotation_debug", linkageName: "test__trap_annotation_debug", scope: !3, file: !3, line: 1, type: !5, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !6) +!5 = !DISubroutineType(types: !6) +!6 = !{} +!7 = !DILocation(line: 4, column: 1, scope: !4) +!8 = !{!"ppc-trap-reason", !"1", !"2"} +declare void @llvm.ppc.trap(i32 %a) +define dso_local void @sub_test() { + call void @llvm.ppc.trap(i32 1), !annotation !8 + ret void +} +define dso_local void @test__trap_annotation_debug(i32 %a) !dbg !4 { + call void @llvm.ppc.trap(i32 %a), !annotation !8 + call void @sub_test() + call void @llvm.ppc.trap(i32 %a), !annotation !8 + ret void +} + +; SYMS32: Index: [[#IND:]]{{.*}}{{[[:space:]] *}}Name: .sub_test +; SYMS32-NEXT: Value (RelocatableAddress): 0x0 +; SYMS32-NEXT: Section: .text +; SYMS32-NEXT: Type: 0x20 +; SYMS32-NEXT: StorageClass: C_EXT (0x2) +; SYMS32-NEXT: NumberOfAuxEntries: 2 +; SYMS32-NEXT: Function Auxiliary Entry { +; SYMS32-NEXT: Index: [[#IND+1]] +; SYMS32-NEXT: OffsetToExceptionTable: 0x2A8 +; SYMS32-NEXT: SizeOfFunction: 0xC +; SYMS32-NEXT: PointerToLineNum: 0x0 +; SYMS32-NEXT: SymbolIndexOfNextBeyond: [[#IND+3]] +; SYMS32-NEXT: } +; SYMS32-NEXT: CSECT Auxiliary Entry { +; SYMS32-NEXT: Index: [[#IND+2]] +; SYMS32-NEXT: ContainingCsectSymbolIndex: 1 +; SYMS32-NEXT: ParameterHashIndex: 0x0 +; SYMS32-NEXT: TypeChkSectNum: 0x0 +; SYMS32-NEXT: SymbolAlignmentLog2: 0 +; SYMS32-NEXT: SymbolType: XTY_LD (0x2) +; SYMS32-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS32-NEXT: StabInfoIndex: 0x0 +; SYMS32-NEXT: StabSectNum: 0x0 +; SYMS32-NEXT: } +; SYMS32-NEXT: } +; SYMS32-NEXT: Symbol { +; SYMS32-NEXT: Index: [[#IND+3]] +; SYMS32-NEXT: Name: .test__trap_annotation +; SYMS32-NEXT: Value (RelocatableAddress): 0x28 +; SYMS32-NEXT: Section: .text +; SYMS32-NEXT: Type: 0x20 +; SYMS32-NEXT: StorageClass: C_EXT (0x2) +; SYMS32-NEXT: NumberOfAuxEntries: 2 +; SYMS32-NEXT: Function Auxiliary Entry { +; SYMS32-NEXT: Index: [[#IND+4]] +; SYMS32-NEXT: OffsetToExceptionTable: 0x2B4 +; SYMS32-NEXT: SizeOfFunction: 0x34 +; SYMS32-NEXT: PointerToLineNum: 0x0 +; SYMS32-NEXT: SymbolIndexOfNextBeyond: [[#IND+6]] +; SYMS32-NEXT: } +; SYMS32-NEXT: CSECT Auxiliary Entry { +; SYMS32-NEXT: Index: [[#IND+5]] +; SYMS32-NEXT: ContainingCsectSymbolIndex: 1 +; SYMS32-NEXT: ParameterHashIndex: 0x0 +; SYMS32-NEXT: TypeChkSectNum: 0x0 +; SYMS32-NEXT: SymbolAlignmentLog2: 0 +; SYMS32-NEXT: SymbolType: XTY_LD (0x2) +; SYMS32-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS32-NEXT: StabInfoIndex: 0x0 +; SYMS32-NEXT: StabSectNum: 0x0 +; SYMS32-NEXT: } +; SYMS32-NEXT: } + +; SYMS64: Index: [[#IND:]]{{.*}}{{[[:space:]] *}}Name: .sub_test +; SYMS64-NEXT: Value (RelocatableAddress): 0x0 +; SYMS64-NEXT: Section: .text +; SYMS64-NEXT: Type: 0x0 +; SYMS64-NEXT: StorageClass: C_EXT (0x2) +; SYMS64-NEXT: NumberOfAuxEntries: 3 +; SYMS64-NEXT: Exception Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+1]] +; SYMS64-NEXT: OffsetToExceptionTable: 0x398 +; SYMS64-NEXT: SizeOfFunction: 0x18 +; SYMS64-NEXT: SymbolIndexOfNextBeyond: [[#IND+4]] +; SYMS64-NEXT: Auxiliary Type: AUX_EXCEPT (0xFF) +; SYMS64-NEXT: } +; SYMS64-NEXT: Function Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+2]] +; SYMS64-NEXT: SizeOfFunction: 0x18 +; SYMS64-NEXT: PointerToLineNum: 0x0 +; SYMS64-NEXT: SymbolIndexOfNextBeyond: [[#IND+4]] +; SYMS64-NEXT: Auxiliary Type: AUX_FCN (0xFE) +; SYMS64-NEXT: } +; SYMS64-NEXT: CSECT Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+3]] +; SYMS64-NEXT: ContainingCsectSymbolIndex: 1 +; SYMS64-NEXT: ParameterHashIndex: 0x0 +; SYMS64-NEXT: TypeChkSectNum: 0x0 +; SYMS64-NEXT: SymbolAlignmentLog2: 0 +; SYMS64-NEXT: SymbolType: XTY_LD (0x2) +; SYMS64-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYMS64-NEXT: } +; SYMS64-NEXT: } +; SYMS64-NEXT: Symbol { +; SYMS64-NEXT: Index: [[#IND+4]] +; SYMS64-NEXT: Name: .test__trap_annotation_debug +; SYMS64-NEXT: Value (RelocatableAddress): 0x28 +; SYMS64-NEXT: Section: .text +; SYMS64-NEXT: Type: 0x0 +; SYMS64-NEXT: StorageClass: C_EXT (0x2) +; SYMS64-NEXT: NumberOfAuxEntries: 3 +; SYMS64-NEXT: Exception Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+5]] +; SYMS64-NEXT: OffsetToExceptionTable: 0x3AC +; SYMS64-NEXT: SizeOfFunction: 0x68 +; SYMS64-NEXT: SymbolIndexOfNextBeyond: [[#IND+8]] +; SYMS64-NEXT: Auxiliary Type: AUX_EXCEPT (0xFF) +; SYMS64-NEXT: } +; SYMS64-NEXT: Function Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+6]] +; SYMS64-NEXT: SizeOfFunction: 0x68 +; SYMS64-NEXT: PointerToLineNum: 0x0 +; SYMS64-NEXT: SymbolIndexOfNextBeyond: [[#IND+8]] +; SYMS64-NEXT: Auxiliary Type: AUX_FCN (0xFE) +; SYMS64-NEXT: } +; SYMS64-NEXT: CSECT Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+7]] +; SYMS64-NEXT: ContainingCsectSymbolIndex: 1 +; SYMS64-NEXT: ParameterHashIndex: 0x0 +; SYMS64-NEXT: TypeChkSectNum: 0x0 +; SYMS64-NEXT: SymbolAlignmentLog2: 0 +; SYMS64-NEXT: SymbolType: XTY_LD (0x2) +; SYMS64-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYMS64-NEXT: } +; SYMS64-NEXT: } diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section.ll @@ -0,0 +1,200 @@ +; Testing 32-bit and 64-bit exception section entries, no exception auxilliary +; entries should be produced as no debug information is specified. +; RUN: llc -mtriple=powerpc-ibm-aix-xcoff -filetype=obj -o %t_32.o < %s +; RUN: llvm-readobj --exception-section %t_32.o | FileCheck %s --check-prefix=EXCEPT +; RUN: llvm-readobj --section-headers %t_32.o | FileCheck %s --check-prefix=READ +; RUN: llvm-readobj --syms %t_32.o | FileCheck %s --check-prefix=SYMS + +; RUN: llc -mtriple=powerpc64-unknown-aix -filetype=obj -o %t_64.o < %s +; RUN: llvm-readobj --exception-section %t_64.o | FileCheck %s --check-prefix=EXCEPT64 +; RUN: llvm-readobj --section-headers %t_64.o | FileCheck %s --check-prefix=READ64 +; RUN: llvm-readobj --syms %t_64.o | FileCheck %s --check-prefix=SYMS64 + +!1 = !{!"ppc-trap-reason", !"1", !"2"} +declare void @llvm.ppc.trap(i32 %a) +define dso_local void @sub_test() { + call void @llvm.ppc.trap(i32 1), !annotation !1 + ret void +} +define dso_local void @test__trap_annotation(i32 %a) { + call void @llvm.ppc.trap(i32 %a), !annotation !1 + call void @sub_test() + call void @llvm.ppc.trap(i32 %a), !annotation !1 + ret void +} + +; EXCEPT: Exception section { +; EXCEPT-NEXT: Symbol: .sub_test (3) +; EXCEPT-NEXT: LangID: 0 +; EXCEPT-NEXT: Reason: 0 +; EXCEPT-NEXT: Trap Instr Addr: 0x4 +; EXCEPT-NEXT: LangID: 1 +; EXCEPT-NEXT: Reason: 2 +; EXCEPT-NEXT: Symbol: .test__trap_annotation (6) +; EXCEPT-NEXT: LangID: 0 +; EXCEPT-NEXT: Reason: 0 +; EXCEPT-NEXT: Trap Instr Addr: 0x3C +; EXCEPT-NEXT: LangID: 1 +; EXCEPT-NEXT: Reason: 2 +; EXCEPT-NEXT: Trap Instr Addr: 0x44 +; EXCEPT-NEXT: LangID: 1 +; EXCEPT-NEXT: Reason: 2 +; EXCEPT-NEXT: } + +; There are multiple "Section {" lines in the readobj output so we need to start this READ check +; on a unique line (Type: STYP_DATA (0x40)) so that the checks know where to start reading +; READ: Type: STYP_DATA (0x40) +; READ-NEXT: } +; READ-NEXT: Section { +; READ-NEXT: Index: 3 +; READ-NEXT: Name: .except +; READ-NEXT: PhysicalAddress: 0x0 +; READ-NEXT: VirtualAddress: 0x0 +; READ-NEXT: Size: 0x1E +; READ-NEXT: RawDataOffset: 0x12C +; READ-NEXT: RelocationPointer: 0x0 +; READ-NEXT: LineNumberPointer: 0x0 +; READ-NEXT: NumberOfRelocations: 0 +; READ-NEXT: NumberOfLineNumbers: 0 +; READ-NEXT: Type: STYP_EXCEPT (0x100) +; READ-NEXT: } +; READ-NEXT: ] + +; SYMS: Index: [[#IND:]]{{.*}}{{[[:space:]] *}}Name: .sub_test +; SYMS-NEXT: Value (RelocatableAddress): 0x0 +; SYMS-NEXT: Section: .text +; SYMS-NEXT: Type: 0x20 +; SYMS-NEXT: StorageClass: C_EXT (0x2) +; SYMS-NEXT: NumberOfAuxEntries: 2 +; SYMS-NEXT: Function Auxiliary Entry { +; SYMS-NEXT: Index: [[#IND+1]] +; SYMS-NEXT: OffsetToExceptionTable: 0x12C +; SYMS-NEXT: SizeOfFunction: 0xC +; SYMS-NEXT: PointerToLineNum: 0x0 +; SYMS-NEXT: SymbolIndexOfNextBeyond: [[#IND+3]] +; SYMS-NEXT: } +; SYMS-NEXT: CSECT Auxiliary Entry { +; SYMS-NEXT: Index: [[#IND+2]] +; SYMS-NEXT: ContainingCsectSymbolIndex: 1 +; SYMS-NEXT: ParameterHashIndex: 0x0 +; SYMS-NEXT: TypeChkSectNum: 0x0 +; SYMS-NEXT: SymbolAlignmentLog2: 0 +; SYMS-NEXT: SymbolType: XTY_LD (0x2) +; SYMS-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS-NEXT: StabInfoIndex: 0x0 +; SYMS-NEXT: StabSectNum: 0x0 +; SYMS-NEXT: } +; SYMS-NEXT: } +; SYMS-NEXT: Symbol { +; SYMS-NEXT: Index: [[#IND+3]] +; SYMS-NEXT: Name: .test__trap_annotation +; SYMS-NEXT: Value (RelocatableAddress): 0x28 +; SYMS-NEXT: Section: .text +; SYMS-NEXT: Type: 0x20 +; SYMS-NEXT: StorageClass: C_EXT (0x2) +; SYMS-NEXT: NumberOfAuxEntries: 2 +; SYMS-NEXT: Function Auxiliary Entry { +; SYMS-NEXT: Index: [[#IND+4]] +; SYMS-NEXT: OffsetToExceptionTable: 0x138 +; SYMS-NEXT: SizeOfFunction: 0x34 +; SYMS-NEXT: PointerToLineNum: 0x0 +; SYMS-NEXT: SymbolIndexOfNextBeyond: [[#IND+6]] +; SYMS-NEXT: } +; SYMS-NEXT: CSECT Auxiliary Entry { +; SYMS-NEXT: Index: [[#IND+5]] +; SYMS-NEXT: ContainingCsectSymbolIndex: 1 +; SYMS-NEXT: ParameterHashIndex: 0x0 +; SYMS-NEXT: TypeChkSectNum: 0x0 +; SYMS-NEXT: SymbolAlignmentLog2: 0 +; SYMS-NEXT: SymbolType: XTY_LD (0x2) +; SYMS-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS-NEXT: StabInfoIndex: 0x0 +; SYMS-NEXT: StabSectNum: 0x0 +; SYMS-NEXT: } +; SYMS-NEXT: } + +; EXCEPT64: Exception section { +; EXCEPT64-NEXT: Symbol: .sub_test (3) +; EXCEPT64-NEXT: LangID: 0 +; EXCEPT64-NEXT: Reason: 0 +; EXCEPT64-NEXT: Trap Instr Addr: 0x4 +; EXCEPT64-NEXT: LangID: 1 +; EXCEPT64-NEXT: Reason: 2 +; EXCEPT64-NEXT: Symbol: .test__trap_annotation (6) +; EXCEPT64-NEXT: LangID: 0 +; EXCEPT64-NEXT: Reason: 0 +; EXCEPT64-NEXT: Trap Instr Addr: 0x3C +; EXCEPT64-NEXT: LangID: 1 +; EXCEPT64-NEXT: Reason: 2 +; EXCEPT64-NEXT: Trap Instr Addr: 0x44 +; EXCEPT64-NEXT: LangID: 1 +; EXCEPT64-NEXT: Reason: 2 +; EXCEPT64-NEXT: } + +; READ64: Type: STYP_DATA (0x40) +; READ64-NEXT: } +; READ64-NEXT: Section { +; READ64-NEXT: Index: 3 +; READ64-NEXT: Name: .except +; READ64-NEXT: PhysicalAddress: 0x0 +; READ64-NEXT: VirtualAddress: 0x0 +; READ64-NEXT: Size: 0x32 +; READ64-NEXT: RawDataOffset: 0x1A8 +; READ64-NEXT: RelocationPointer: 0x0 +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 0 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: Type: STYP_EXCEPT (0x100) +; READ64-NEXT: } +; READ64-NEXT: ] + +; SYMS64: Index: [[#IND:]]{{.*}}{{[[:space:]] *}}Name: .sub_test +; SYMS64-NEXT: Value (RelocatableAddress): 0x0 +; SYMS64-NEXT: Section: .text +; SYMS64-NEXT: Type: 0x0 +; SYMS64-NEXT: StorageClass: C_EXT (0x2) +; SYMS64-NEXT: NumberOfAuxEntries: 2 +; SYMS64-NEXT: Function Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+1]] +; SYMS64-NEXT: SizeOfFunction: 0x18 +; SYMS64-NEXT: PointerToLineNum: 0x0 +; SYMS64-NEXT: SymbolIndexOfNextBeyond: [[#IND+3]] +; SYMS64-NEXT: Auxiliary Type: AUX_FCN (0xFE) +; SYMS64-NEXT: } +; SYMS64-NEXT: CSECT Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+2]] +; SYMS64-NEXT: ContainingCsectSymbolIndex: 1 +; SYMS64-NEXT: ParameterHashIndex: 0x0 +; SYMS64-NEXT: TypeChkSectNum: 0x0 +; SYMS64-NEXT: SymbolAlignmentLog2: 0 +; SYMS64-NEXT: SymbolType: XTY_LD (0x2) +; SYMS64-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYMS64-NEXT: } +; SYMS64-NEXT: } +; SYMS64-NEXT: Symbol { +; SYMS64-NEXT: Index: [[#IND+3]] +; SYMS64-NEXT: Name: .test__trap_annotation +; SYMS64-NEXT: Value (RelocatableAddress): 0x28 +; SYMS64-NEXT: Section: .text +; SYMS64-NEXT: Type: 0x0 +; SYMS64-NEXT: StorageClass: C_EXT (0x2) +; SYMS64-NEXT: NumberOfAuxEntries: 2 +; SYMS64-NEXT: Function Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+4]] +; SYMS64-NEXT: SizeOfFunction: 0x68 +; SYMS64-NEXT: PointerToLineNum: 0x0 +; SYMS64-NEXT: SymbolIndexOfNextBeyond: [[#IND+6]] +; SYMS64-NEXT: Auxiliary Type: AUX_FCN (0xFE) +; SYMS64-NEXT: } +; SYMS64-NEXT: CSECT Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+5]] +; SYMS64-NEXT: ContainingCsectSymbolIndex: 1 +; SYMS64-NEXT: ParameterHashIndex: 0x0 +; SYMS64-NEXT: TypeChkSectNum: 0x0 +; SYMS64-NEXT: SymbolAlignmentLog2: 0 +; SYMS64-NEXT: SymbolType: XTY_LD (0x2) +; SYMS64-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYMS64-NEXT: } +; SYMS64-NEXT: } diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-td.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-td.ll --- a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-td.ll +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-td.ll @@ -4,10 +4,12 @@ ; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \ ; RUN: --ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s -check-prefix=AIX -; RUN: not --crash llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \ -; RUN: --ppc-asm-full-reg-names -mcpu=pwr8 --filetype=obj -o /dev/null %s 2>&1 | FileCheck %s -check-prefix=OBJ +; RUN: llc -mtriple=powerpc64-unknown-aix -filetype=obj -o %t_64.o < %s +; RUN: llvm-readobj --exception-section %t_64.o | FileCheck %s --check-prefix=OBJ64 -; OBJ: LLVM ERROR: emitXCOFFExceptDirective not yet supported for integrated assembler path. +; Check that we do not crash in object mode +; OBJ64: Exception section { +; OBJ64-NEXT: Symbol: .test__trapd_annotation (3) !1 = !{!"ppc-trap-reason", !"1", !"2"} declare void @llvm.ppc.trapd(i64 %a) diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-tw.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-tw.ll --- a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-tw.ll +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-tw.ll @@ -8,10 +8,12 @@ ; RUN: --ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s -check-prefix=AIX ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \ ; RUN: --ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s -check-prefix=AIX -; RUN: not --crash llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \ -; RUN: --ppc-asm-full-reg-names -mcpu=pwr8 --filetype=obj -o /dev/null %s 2>&1 | FileCheck %s -check-prefix=OBJ +; RUN: llc -mtriple=powerpc-ibm-aix-xcoff -filetype=obj -o %t_32.o < %s +; RUN: llvm-readobj --exception-section %t_32.o | FileCheck %s --check-prefix=OBJ -; OBJ: LLVM ERROR: emitXCOFFExceptDirective not yet supported for integrated assembler path. +; Check that we do not crash in object mode +; OBJ: Exception section { +; OBJ-NEXT: Symbol: .test__trap_annotation (3) !1 = !{!"ppc-trap-reason", !"1", !"2"} declare void @llvm.ppc.trap(i32 %a) @@ -47,3 +49,4 @@ call void @llvm.ppc.tw(i32 4, i32 %a, i32 0), !annotation !1 ret void } +