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/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -4571,6 +4571,12 @@ const AsmOperandInfo &OpInfo, SelectionDAG &DAG) const; + // Lower target intrinsic instruction. + virtual void LowerTargetIntrinsic(const CallInst &I, SDValue &Op, + SmallVector &Ops, + SelectionDAG &DAG) const; + + //===--------------------------------------------------------------------===// // Div utility functions // 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,10 @@ std::vector &getAddrsigSyms() { return AddrsigSyms; } + virtual void addExceptionEntry(const MCSymbol *Symbol, MCSymbol *Trap, + unsigned LanguageCode, unsigned ReasonCode, + unsigned FunctionSize, bool hasDebug) {} + /// 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 @@ -628,6 +628,16 @@ /// changed at the end of assembly. virtual void emitXCOFFRenameDirective(const MCSymbol *Name, StringRef Rename); + /// Emit an XCOFF .except directive which adds information about + /// a trap instruction to the object file exception section + /// + /// \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, + unsigned Lang, unsigned Reason, + unsigned FunctionSize, bool hasDebug); + /// Emit a XCOFF .ref directive which creates R_REF type entry in the /// relocation table for one or more symbols. /// 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,6 +41,9 @@ report_fatal_error("emitXCOFFRenameDirective is not implemented yet on " "object generation path"); } + void emitXCOFFExceptDirective(const MCSymbol *Symbol, MCSymbol *Trap, + unsigned Lang, unsigned Reason, + unsigned FunctionSize, bool hasDebug) override; }; } // end namespace llvm diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -4865,6 +4865,7 @@ // Create the node. SDValue Result; + TLI.LowerTargetIntrinsic(I, Result, Ops, DAG); if (IsTgtIntrinsic) { // This is target intrinsic that touches memory Result = diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -5254,6 +5254,12 @@ } } +void TargetLowering::LowerTargetIntrinsic(const CallInst &I, SDValue &Op, + SmallVector &Ops, + SelectionDAG &DAG) const { + return; +} + std::pair TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *RI, StringRef Constraint, 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,6 +197,10 @@ void emitXCOFFRefDirective(StringRef Name) override; + void emitXCOFFExceptDirective(const MCSymbol *Symbol, MCSymbol *Trap, + unsigned Lang, unsigned Reason, + unsigned FunctionSize, bool hasDebug) override; + void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; @@ -942,6 +946,15 @@ EmitEOL(); } +void MCAsmStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, + MCSymbol *Trap, unsigned Lang, unsigned Reason, + unsigned FunctionSize, bool hasDebug) { + OS << "\t.except\t"; + Symbol->print(OS, MAI); + OS << ", " << Lang << ", " << Reason; + EmitEOL(); +} + void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { assert(MAI->hasDotTypeDotSizeDirective()); OS << "\t.size\t"; 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 @@ -1190,6 +1190,13 @@ llvm_unreachable("emitXCOFFRefDirective is only supported on XCOFF targets"); } +void MCStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, + MCSymbol *Trap, unsigned Lang, unsigned Reason, + unsigned FunctionSize, bool hasDebug) { + llvm_unreachable("emitXCOFFExceptDirective is only supported on " + "XCOFF targets"); +} + void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} void MCStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name, bool KeepOriginalSym) {} 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 @@ -81,6 +81,15 @@ emitSymbolAttribute(Symbol, Visibility); } +void MCXCOFFStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, + MCSymbol *Trap, unsigned Lang, + unsigned Reason, + unsigned FunctionSize, + bool hasDebug) { + getAssembler().getWriter().addExceptionEntry(Symbol, Trap, Lang, Reason, + FunctionSize, hasDebug); +} + void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { getAssembler().registerSymbol(*Symbol); 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 @@ -199,6 +199,36 @@ virtual ~DwarfSectionEntry() = default; }; +struct ExceptionTableEntry { + MCSymbol *Trap; + unsigned TrapAddress; + unsigned Lang; + unsigned Reason; + + ExceptionTableEntry(MCSymbol *Trap, unsigned Lang, unsigned Reason) : + Trap(Trap), Lang(Lang), Reason(Reason) {} +}; + +struct ExceptionInfo { + const MCSymbol *Symbol; + unsigned FunctionSize; + std::vector Entries; +}; + +struct ExceptionSectionEntry : public SectionEntry { + std::vector ExceptionTable; + bool isDebugEnabled; + + ExceptionSectionEntry(StringRef N, int32_t Flags) : + SectionEntry(N, Flags | XCOFF::STYP_EXCEPT) { + memcpy(Name, N.data(), N.size()); + } + + ExceptionSectionEntry(ExceptionSectionEntry &&s) = default; + + virtual ~ExceptionSectionEntry() = default; +}; + class XCOFFObjectWriter : public MCObjectWriter { uint32_t SymbolTableEntryCount = 0; @@ -251,6 +281,8 @@ std::vector DwarfSections; + ExceptionSectionEntry ExceptionSection; + CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); void reset() override; @@ -287,12 +319,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 +351,16 @@ // `Sections`. void assignAddressesAndIndices(const MCAsmLayout &); void finalizeSectionInfo(); + void addExceptionEntry(const MCSymbol *Symbol, MCSymbol *Trap, + unsigned LanguageCode, unsigned ReasonCode, + unsigned FunctionSize, bool hasDebug) override; + + // TODO aux header support not implemented. + bool needsAuxiliaryHeader() const { return false; } + + bool hasExceptionSection() { return (bool) getExceptionSectionSize(); } + unsigned getExceptionSectionSize(); + unsigned getExceptionOffset(const MCSymbol *Symbol); size_t auxiliaryHeaderSize() const { // 64-bit object files have no auxiliary header. @@ -337,7 +389,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 +403,7 @@ Sec->reset(); for (auto &DwarfSec : DwarfSections) DwarfSec.reset(); + ExceptionSection.reset(); // Reset states in XCOFFObjectWriter. SymbolTableEntryCount = 0; @@ -634,6 +688,8 @@ for (const auto &DwarfSection : DwarfSections) writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection, CurrentAddressLocation); + writeSectionForExceptionSectionEntry(Asm, Layout, ExceptionSection, + CurrentAddressLocation); } uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, @@ -689,8 +745,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,6 +788,34 @@ assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address && "Symbol address overflowed."); + for (auto &SymbolEntry : ExceptionSection.ExceptionTable) { + if(SymbolRef.MCSym == SymbolEntry.Symbol) { + writeSymbolEntry(SymbolRef.getSymbolTableName(), + CSectionRef.Address + SymbolOffset, SectionIndex, + is64Bit() ? SymbolRef.getVisibilityType() : + SymbolRef.getVisibilityType() | 0x0020, + SymbolRef.getStorageClass(), + (is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2); + + if(is64Bit() && ExceptionSection.isDebugEnabled) { + writeSymbolAuxExceptionEntry(ExceptionSection.FileOffsetToData + + getExceptionOffset(SymbolEntry.Symbol), + SymbolEntry.FunctionSize, + SymbolIndexMap[SymbolEntry.Symbol] + 4); + } + writeSymbolAuxFunctionEntry(ExceptionSection.FileOffsetToData + + getExceptionOffset(SymbolEntry.Symbol), + SymbolEntry.FunctionSize, 0, + (is64Bit() && ExceptionSection.isDebugEnabled) ? + SymbolIndexMap[SymbolEntry.Symbol] + 4 : + SymbolIndexMap[SymbolEntry.Symbol] + 3); + + writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD, + CSectionRef.MCSec->getMappingClass()); + return; + } + } + writeSymbolEntry(SymbolRef.getSymbolTableName(), CSectionRef.Address + SymbolOffset, SectionIndex, SymbolRef.getVisibilityType(), SymbolRef.getStorageClass()); @@ -762,6 +844,32 @@ 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()) W.write(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 +941,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 +1084,54 @@ SymbolTableOffset = RawPointer; } +void XCOFFObjectWriter::addExceptionEntry( + const MCSymbol *Symbol, 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; + for(auto &SymbolEntry : ExceptionSection.ExceptionTable) { + if (Symbol == SymbolEntry.Symbol) { + SymbolEntry.Entries.push_back( + ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); + return; + } + } + ExceptionInfo NewEntry; + NewEntry.Symbol = Symbol; + NewEntry.FunctionSize = FunctionSize; + NewEntry.Entries.push_back( + ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); + ExceptionSection.ExceptionTable.push_back(NewEntry); +} + +unsigned XCOFFObjectWriter::getExceptionSectionSize() { + unsigned Size = 0; + for(auto &SymbolEntry : ExceptionSection.ExceptionTable) { + Size += (is64Bit()) ? (SymbolEntry.Entries.size() + 1) * + XCOFF::ExceptionSectionEntrySize64 : + (SymbolEntry.Entries.size() + 1) * + XCOFF::ExceptionSectionEntrySize32; + } + return Size; +} + +unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol *Symbol) { + unsigned Offset = 0; + for(auto &SymbolEntry : ExceptionSection.ExceptionTable) { + if(Symbol == SymbolEntry.Symbol) return Offset; + Offset += (is64Bit()) ? XCOFF::ExceptionSectionEntrySize64 : + XCOFF::ExceptionSectionEntrySize32; + for(auto &TrapEntry : SymbolEntry.Entries) { + (void) TrapEntry; + Offset += (is64Bit()) ? XCOFF::ExceptionSectionEntrySize64 : + XCOFF::ExceptionSectionEntrySize32; + } + } + return Offset; +} + void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) { // The symbol table starts with all the C_FILE symbols. uint32_t SymbolTableIndex = FileNames.size(); @@ -1035,11 +1193,27 @@ SymbolTableIndex += 2; for (auto &Sym : Csect.Syms) { + bool hasExceptEntry = false; + for (auto &SymbolEntry : ExceptionSection.ExceptionTable) { + if (SymbolEntry.Symbol == Sym.MCSym) { + hasExceptEntry = true; + for(auto &TrapEntry : SymbolEntry.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. 1 or 2 additional auxiliary entries if exception section + // present. SymbolTableIndex += 2; + if(hasExceptionSection() && hasExceptEntry) { + if(is64Bit() && ExceptionSection.isDebugEnabled) + SymbolTableIndex += 2; + else SymbolTableIndex += 1; + } } } @@ -1109,7 +1283,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 +1325,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 +1411,29 @@ CurrentAddressLocation += TailPaddingSize; } +void XCOFFObjectWriter::writeSectionForExceptionSectionEntry( + const MCAssembler &Asm, const MCAsmLayout &Layout, + ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation) { + for(auto const &SymbolEntry : ExceptionEntry.ExceptionTable) { + W.write(SymbolIndexMap[SymbolEntry.Symbol]); + if (is64Bit()) { + W.OS.write_zeros(4); + } + W.OS.write_zeros(2); + for(auto &TrapEntry : SymbolEntry.Entries) { + if (is64Bit()) { + W.write(TrapEntry.TrapAddress); + } else { + W.write(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/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -2646,6 +2646,25 @@ switch (MI->getOpcode()) { default: break; + case PPC::TW: + case PPC::TWI: + case PPC::TD: + case PPC::TDI: { + if (MI->getNumOperands() < 5) + break; + const MachineOperand &LangMO = MI->getOperand(3); + const MachineOperand &ReasonMO = MI->getOperand(4); + if (!LangMO.isImm() || !ReasonMO.isImm()) + break; + MCSymbol *TempSym = OutContext.createNamedTempSymbol(); + OutStreamer->emitLabel(TempSym); + OutStreamer->emitXCOFFExceptDirective(CurrentFnSym, TempSym, + LangMO.getImm(), ReasonMO.getImm(), + Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 8 : + MI->getMF()->getInstructionCount() * 4, + MMI->hasDebugInfo()); + break; + } case PPC::GETtlsADDR64AIX: case PPC::GETtlsADDR32AIX: { // The reference to .__tls_get_addr is unknown to the assembler diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -5053,8 +5053,18 @@ case ISD::INTRINSIC_VOID: { auto IntrinsicID = N->getConstantOperandVal(1); - if (IntrinsicID == Intrinsic::ppc_tdw || IntrinsicID == Intrinsic::ppc_tw) { - unsigned Opcode = IntrinsicID == Intrinsic::ppc_tdw ? PPC::TDI : PPC::TWI; + if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw && + IntrinsicID != Intrinsic::ppc_trapd && + IntrinsicID != Intrinsic::ppc_trap) + break; + unsigned Opcode = (IntrinsicID == Intrinsic::ppc_tdw || + IntrinsicID == Intrinsic::ppc_trapd) + ? PPC::TDI + : PPC::TWI; + SmallVector OpsWithMD; + unsigned MDIndex; + if (IntrinsicID == Intrinsic::ppc_tdw || + IntrinsicID == Intrinsic::ppc_tw) { SDValue Ops[] = {N->getOperand(4), N->getOperand(2), N->getOperand(3)}; int16_t SImmOperand2; int16_t SImmOperand3; @@ -5090,10 +5100,31 @@ Ops[1] = N->getOperand(3); Ops[2] = getI32Imm(int(SImmOperand2) & 0xFFFF, dl); } - CurDAG->SelectNodeTo(N, Opcode, MVT::Other, Ops); - return; + OpsWithMD = {Ops[0], Ops[1], Ops[2]}; + MDIndex = 5; + } else { + OpsWithMD = {getI32Imm(24, dl), N->getOperand(2), getI32Imm(0, dl)}; + MDIndex = 3; + } + + if (N->getNumOperands() > MDIndex) { + SDValue MDV = N->getOperand(MDIndex); + const MDNode *MD = cast(MDV)->getMD(); + assert(MD->getNumOperands() != 0 && "Empty MDNode in operands!"); + assert((isa(MD->getOperand(0)) && cast( + MD->getOperand(0))->getString().equals("ppc-trap-reason")) + && "Unsupported annotation data type!"); + for (unsigned i = 1; i < MD->getNumOperands(); i++) { + assert(isa(MD->getOperand(i)) && + "Invalid data type for annotation ppc-trap-reason!"); + OpsWithMD.push_back( + getI32Imm(std::stoi(cast( + MD->getOperand(i))->getString().str()), dl)); + } } - break; + OpsWithMD.push_back(N->getOperand(0)); // chain + CurDAG->SelectNodeTo(N, Opcode, MVT::Other, OpsWithMD); + return; } case ISD::INTRINSIC_WO_CHAIN: { diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -995,6 +995,10 @@ return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); } + void LowerTargetIntrinsic(const CallInst &I, SDValue &Op, + SmallVector &Ops, + SelectionDAG &DAG) const override; + /// isLegalAddressingMode - Return true if the addressing mode represented /// by AM is legal for this target, for a load/store of the specified type. bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -16230,6 +16230,25 @@ TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); } +void PPCTargetLowering::LowerTargetIntrinsic(const CallInst &I, SDValue &Op, + SmallVector &Ops, + SelectionDAG &DAG) const { + if (I.getNumOperands() <= 1) + return; + if (!isa(Ops[1].getNode())) + return; + auto IntrinsicID = cast(Ops[1].getNode())->getZExtValue(); + if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw && + IntrinsicID != Intrinsic::ppc_trapd && IntrinsicID != Intrinsic::ppc_trap) + return; + + if (I.hasMetadata("annotation")) { + MDNode *MDN = I.getMetadata("annotation"); + Ops.push_back(DAG.getMDNode(MDN)); + } + return; +} + // isLegalAddressingMode - Return true if the addressing mode represented // by AM is legal for this target, for a load/store of the specified type. bool PPCTargetLowering::isLegalAddressingMode(const DataLayout &DL, diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1973,9 +1973,6 @@ def : Pat<(int_ppc_stdcx ForceXForm:$dst, g8rc:$A), (STDCX g8rc:$A, ForceXForm:$dst)>; -// trapd -def : Pat<(int_ppc_trapd g8rc:$A), - (TDI 24, $A, 0)>; def : Pat<(i64 (int_ppc_mfspr timm:$SPR)), (MFSPR8 $SPR)>; def : Pat<(int_ppc_mtspr timm:$SPR, g8rc:$RT), diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -1770,13 +1770,13 @@ let isTerminator = 1, isBarrier = 1, hasCtrlDep = 1 in def TRAP : XForm_24<31, 4, (outs), (ins), "trap", IIC_LdStLoad, [(trap)]>; -def TWI : DForm_base<3, (outs), (ins u5imm:$to, gprc:$rA, s16imm:$imm), +def TWI : DForm_base<3, (outs), (ins u5imm:$to, gprc:$rA, s16imm:$imm, variable_ops), "twi $to, $rA, $imm", IIC_IntTrapW, []>; -def TW : XForm_1<31, 4, (outs), (ins u5imm:$to, gprc:$rA, gprc:$rB), +def TW : XForm_1<31, 4, (outs), (ins u5imm:$to, gprc:$rA, gprc:$rB, variable_ops), "tw $to, $rA, $rB", IIC_IntTrapW, []>; -def TDI : DForm_base<2, (outs), (ins u5imm:$to, g8rc:$rA, s16imm:$imm), +def TDI : DForm_base<2, (outs), (ins u5imm:$to, g8rc:$rA, s16imm:$imm, variable_ops), "tdi $to, $rA, $imm", IIC_IntTrapD, []>; -def TD : XForm_1<31, 68, (outs), (ins u5imm:$to, g8rc:$rA, g8rc:$rB), +def TD : XForm_1<31, 68, (outs), (ins u5imm:$to, g8rc:$rA, g8rc:$rB, variable_ops), "td $to, $rA, $rB", IIC_IntTrapD, []>; def POPCNTB : XForm_11<31, 122, (outs gprc:$rA), (ins gprc:$rS), @@ -5085,8 +5085,6 @@ (STWCX gprc:$A, ForceXForm:$dst)>; def : Pat<(int_ppc_stbcx ForceXForm:$dst, gprc:$A), (STBCX gprc:$A, ForceXForm:$dst)>; -def : Pat<(int_ppc_trap gprc:$A), - (TWI 24, $A, 0)>; def : Pat<(int_ppc_fcfid f64:$A), (XSCVSXDDP $A)>; 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,233 @@ +; RUN: llc -O0 -mtriple=powerpc64-unknown-aix -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --exception-section %t.o | FileCheck %s --check-prefix=EXCEPT64 +; RUN: llc -O0 -mtriple=powerpc64-unknown-aix -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --section-headers %t.o | FileCheck %s --check-prefix=READ64 +; RUN: llc -O0 -mtriple=powerpc64-unknown-aix -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --syms %t.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: "/home/pauls/examples/14687/bounds64.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 +} + +; EXCEPT64: Exception section { +; EXCEPT64-NEXT: Symbol Index: 3 (.sub_test) +; 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 Index: 7 (.test__trap_annotation_debug) +; EXCEPT64-NEXT: LangID: 0 +; EXCEPT64-NEXT: Reason: 0 +; EXCEPT64-NEXT: Trap Instr Addr: 0x38 +; 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: Sections [ +; READ64-NEXT: Section { +; READ64-NEXT: Index: 1 +; READ64-NEXT: Name: .text +; READ64-NEXT: PhysicalAddress: 0x0 +; READ64-NEXT: VirtualAddress: 0x0 +; READ64-NEXT: Size: 0x8C +; READ64-NEXT: RawDataOffset: 0x1C8 +; READ64-NEXT: RelocationPointer: 0x0 +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 0 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: Type: STYP_TEXT (0x20) +; READ64-NEXT: } +; READ64-NEXT: Section { +; READ64-NEXT: Index: 2 +; READ64-NEXT: Name: .data +; READ64-NEXT: PhysicalAddress: 0x90 +; READ64-NEXT: VirtualAddress: 0x90 +; READ64-NEXT: Size: 0x30 +; READ64-NEXT: RawDataOffset: 0x254 +; READ64-NEXT: RelocationPointer: 0x40A +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 4 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: Type: STYP_DATA (0x40) +; READ64-NEXT: } +; READ64-NEXT: Section { +; READ64-NEXT: Index: 3 +; READ64-NEXT: Name: .dwabrev +; READ64-NEXT: PhysicalAddress: 0x0 +; READ64-NEXT: VirtualAddress: 0x0 +; READ64-NEXT: Size: 0x2A +; READ64-NEXT: RawDataOffset: 0x284 +; READ64-NEXT: RelocationPointer: 0x0 +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 0 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: Type: STYP_DWARF (0x10) +; READ64-NEXT: } +; READ64-NEXT: Section { +; READ64-NEXT: Index: 4 +; READ64-NEXT: Name: .dwinfo +; READ64-NEXT: PhysicalAddress: 0x0 +; READ64-NEXT: VirtualAddress: 0x0 +; READ64-NEXT: Size: 0xBC +; READ64-NEXT: RawDataOffset: 0x2C4 +; READ64-NEXT: RelocationPointer: 0x442 +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 6 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: Type: STYP_DWARF (0x10) +; READ64-NEXT: } +; READ64-NEXT: Section { +; READ64-NEXT: Index: 5 +; READ64-NEXT: Name: .dwline +; READ64-NEXT: PhysicalAddress: 0x0 +; READ64-NEXT: VirtualAddress: 0x0 +; READ64-NEXT: Size: 0x52 +; READ64-NEXT: RawDataOffset: 0x384 +; READ64-NEXT: RelocationPointer: 0x0 +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 0 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: Type: STYP_DWARF (0x10) +; READ64-NEXT: } +; READ64-NEXT: Section { +; READ64-NEXT: Index: 6 +; READ64-NEXT: Name: .except +; READ64-NEXT: PhysicalAddress: 0x0 +; READ64-NEXT: VirtualAddress: 0x0 +; READ64-NEXT: Size: 0x32 +; READ64-NEXT: RawDataOffset: 0x3D8 +; READ64-NEXT: RelocationPointer: 0x0 +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 0 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: Type: STYP_EXCEPT (0x100) +; 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: 3 +; SYMS64-NEXT: Exception Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+1]] +; SYMS64-NEXT: OffsetToExceptionTable: 0x3D8 +; 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: 0x3EC +; 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: } +; SYMS64-NEXT: Symbol { +; SYMS64-NEXT: Index: [[#IND+8]] +; SYMS64-NEXT: Name: sub_test +; SYMS64-NEXT: Value (RelocatableAddress): 0x90 +; SYMS64-NEXT: Section: .data +; SYMS64-NEXT: Type: 0x0 +; SYMS64-NEXT: StorageClass: C_EXT (0x2) +; SYMS64-NEXT: NumberOfAuxEntries: 1 +; SYMS64-NEXT: CSECT Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+9]] +; SYMS64-NEXT: SectionLen: 24 +; SYMS64-NEXT: ParameterHashIndex: 0x0 +; SYMS64-NEXT: TypeChkSectNum: 0x0 +; SYMS64-NEXT: SymbolAlignmentLog2: 3 +; SYMS64-NEXT: SymbolType: XTY_SD (0x1) +; SYMS64-NEXT: StorageMappingClass: XMC_DS (0xA) +; SYMS64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYMS64-NEXT: } +; SYMS64-NEXT: } +; SYMS64-NEXT: Symbol { +; SYMS64-NEXT: Index: [[#IND+10]] +; SYMS64-NEXT: Name: test__trap_annotation_debug +; SYMS64-NEXT: Value (RelocatableAddress): 0xA8 +; SYMS64-NEXT: Section: .data +; SYMS64-NEXT: Type: 0x0 +; SYMS64-NEXT: StorageClass: C_EXT (0x2) +; SYMS64-NEXT: NumberOfAuxEntries: 1 +; SYMS64-NEXT: CSECT Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+11]] +; SYMS64-NEXT: SectionLen: 24 +; SYMS64-NEXT: ParameterHashIndex: 0x0 +; SYMS64-NEXT: TypeChkSectNum: 0x0 +; SYMS64-NEXT: SymbolAlignmentLog2: 3 +; SYMS64-NEXT: SymbolType: XTY_SD (0x1) +; SYMS64-NEXT: StorageMappingClass: XMC_DS (0xA) +; 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,344 @@ +; RUN: llc -O0 -mtriple=powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --exception-section %t.o | FileCheck %s --check-prefix=EXCEPT +; RUN: llc -O0 -mtriple=powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --section-headers %t.o | FileCheck %s --check-prefix=READ +; RUN: llc -O0 -mtriple=powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --syms %t.o | FileCheck %s --check-prefix=SYMS +; RUN: llc -O0 -mtriple=powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s +; RUN: llvm-objdump --section-headers %t.o | FileCheck %s --check-prefix=DUMP + +; RUN: llc -O0 -mtriple=powerpc64-unknown-aix -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --exception-section %t.o | FileCheck %s --check-prefix=EXCEPT64 +; RUN: llc -O0 -mtriple=powerpc64-unknown-aix -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --section-headers %t.o | FileCheck %s --check-prefix=READ64 +; RUN: llc -O0 -mtriple=powerpc64-unknown-aix -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --syms %t.o | FileCheck %s --check-prefix=SYMS64 +; RUN: llc -O0 -mtriple=powerpc64-unknown-aix -filetype=obj -o %t.o < %s +; RUN: llvm-objdump --section-headers %t.o | FileCheck %s --check-prefix=DUMP64 + +!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 Index: 3 (.sub_test) +; 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 Index: 6 (.test__trap_annotation) +; EXCEPT-NEXT: LangID: 0 +; EXCEPT-NEXT: Reason: 0 +; EXCEPT-NEXT: Trap Instr Addr: 0x38 +; EXCEPT-NEXT: LangID: 1 +; EXCEPT-NEXT: Reason: 2 +; EXCEPT-NEXT: Trap Instr Addr: 0x44 +; EXCEPT-NEXT: LangID: 1 +; EXCEPT-NEXT: Reason: 2 +; EXCEPT-NEXT: } + +; READ: Sections [ +; READ-NEXT: Section { +; READ-NEXT: Index: 1 +; READ-NEXT: Name: .text +; READ-NEXT: PhysicalAddress: 0x0 +; READ-NEXT: VirtualAddress: 0x0 +; READ-NEXT: Size: 0x84 +; READ-NEXT: RawDataOffset: 0x8C +; READ-NEXT: RelocationPointer: 0x0 +; READ-NEXT: LineNumberPointer: 0x0 +; READ-NEXT: NumberOfRelocations: 0 +; READ-NEXT: NumberOfLineNumbers: 0 +; READ-NEXT: Type: STYP_TEXT (0x20) +; READ-NEXT: } +; READ-NEXT: Section { +; READ-NEXT: Index: 2 +; READ-NEXT: Name: .data +; READ-NEXT: PhysicalAddress: 0x84 +; READ-NEXT: VirtualAddress: 0x84 +; READ-NEXT: Size: 0x18 +; READ-NEXT: RawDataOffset: 0x110 +; READ-NEXT: RelocationPointer: 0x146 +; READ-NEXT: LineNumberPointer: 0x0 +; READ-NEXT: NumberOfRelocations: 4 +; READ-NEXT: NumberOfLineNumbers: 0 +; READ-NEXT: 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: 0x128 +; 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: 0x128 +; 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: 0x134 +; SYMS-NEXT: SizeOfFunction: 0x30 +; 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: } +; SYMS-NEXT: Symbol { +; SYMS-NEXT: Index: [[#IND+6]] +; SYMS-NEXT: Name: sub_test +; SYMS-NEXT: Value (RelocatableAddress): 0x84 +; SYMS-NEXT: Section: .data +; SYMS-NEXT: Type: 0x0 +; SYMS-NEXT: StorageClass: C_EXT (0x2) +; SYMS-NEXT: NumberOfAuxEntries: 1 +; SYMS-NEXT: CSECT Auxiliary Entry { +; SYMS-NEXT: Index: [[#IND+7]] +; SYMS-NEXT: SectionLen: 12 +; SYMS-NEXT: ParameterHashIndex: 0x0 +; SYMS-NEXT: TypeChkSectNum: 0x0 +; SYMS-NEXT: SymbolAlignmentLog2: 2 +; SYMS-NEXT: SymbolType: XTY_SD (0x1) +; SYMS-NEXT: StorageMappingClass: XMC_DS (0xA) +; SYMS-NEXT: StabInfoIndex: 0x0 +; SYMS-NEXT: StabSectNum: 0x0 +; SYMS-NEXT: } +; SYMS-NEXT: } +; SYMS-NEXT: Symbol { +; SYMS-NEXT: Index: [[#IND+8]] +; SYMS-NEXT: Name: test__trap_annotation +; SYMS-NEXT: Value (RelocatableAddress): 0x90 +; SYMS-NEXT: Section: .data +; SYMS-NEXT: Type: 0x0 +; SYMS-NEXT: StorageClass: C_EXT (0x2) +; SYMS-NEXT: NumberOfAuxEntries: 1 +; SYMS-NEXT: CSECT Auxiliary Entry { +; SYMS-NEXT: Index: [[#IND+9]] +; SYMS-NEXT: SectionLen: 12 +; SYMS-NEXT: ParameterHashIndex: 0x0 +; SYMS-NEXT: TypeChkSectNum: 0x0 +; SYMS-NEXT: SymbolAlignmentLog2: 2 +; SYMS-NEXT: SymbolType: XTY_SD (0x1) +; SYMS-NEXT: StorageMappingClass: XMC_DS (0xA) +; SYMS-NEXT: StabInfoIndex: 0x0 +; SYMS-NEXT: StabSectNum: 0x0 +; SYMS-NEXT: } +; SYMS-NEXT: } + +; DUMP: Sections: +; DUMP-NEXT: Idx Name Size VMA Type +; DUMP-NEXT: 0 .text 00000084 00000000 TEXT +; DUMP-NEXT: 1 .data 00000018 00000084 DATA +; DUMP-NEXT: 2 .except 0000001e 00000000 + +; EXCEPT64: Exception section { +; EXCEPT64-NEXT: Symbol Index: 3 (.sub_test) +; 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 Index: 6 (.test__trap_annotation) +; EXCEPT64-NEXT: LangID: 0 +; EXCEPT64-NEXT: Reason: 0 +; EXCEPT64-NEXT: Trap Instr Addr: 0x38 +; 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: Sections [ +; READ64-NEXT: Section { +; READ64-NEXT: Index: 1 +; READ64-NEXT: Name: .text +; READ64-NEXT: PhysicalAddress: 0x0 +; READ64-NEXT: VirtualAddress: 0x0 +; READ64-NEXT: Size: 0x84 +; READ64-NEXT: RawDataOffset: 0xF0 +; READ64-NEXT: RelocationPointer: 0x0 +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 0 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: Type: STYP_TEXT (0x20) +; READ64-NEXT: } +; READ64-NEXT: Section { +; READ64-NEXT: Index: 2 +; READ64-NEXT: Name: .data +; READ64-NEXT: PhysicalAddress: 0x88 +; READ64-NEXT: VirtualAddress: 0x88 +; READ64-NEXT: Size: 0x30 +; READ64-NEXT: RawDataOffset: 0x174 +; READ64-NEXT: RelocationPointer: 0x1D6 +; READ64-NEXT: LineNumberPointer: 0x0 +; READ64-NEXT: NumberOfRelocations: 4 +; READ64-NEXT: NumberOfLineNumbers: 0 +; READ64-NEXT: 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: 0x1A4 +; 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: } +; SYMS64-NEXT: Symbol { +; SYMS64-NEXT: Index: [[#IND+6]] +; SYMS64-NEXT: Name: sub_test +; SYMS64-NEXT: Value (RelocatableAddress): 0x88 +; SYMS64-NEXT: Section: .data +; SYMS64-NEXT: Type: 0x0 +; SYMS64-NEXT: StorageClass: C_EXT (0x2) +; SYMS64-NEXT: NumberOfAuxEntries: 1 +; SYMS64-NEXT: CSECT Auxiliary Entry { +; SYMS64-NEXT: Index: [[#IND+7]] +; SYMS64-NEXT: SectionLen: 24 +; SYMS64-NEXT: ParameterHashIndex: 0x0 +; SYMS64-NEXT: TypeChkSectNum: 0x0 +; SYMS64-NEXT: SymbolAlignmentLog2: 3 +; SYMS64-NEXT: SymbolType: XTY_SD (0x1) +; SYMS64-NEXT: StorageMappingClass: XMC_DS (0xA) +; SYMS64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYMS64-NEXT: } +; SYMS64-NEXT: } +; SYMS64-NEXT: Symbol { +; SYMS64-NEXT: Index: [[#IND+8]] +; SYMS64-NEXT: Name: test__trap_annotation +; SYMS64-NEXT: Value (RelocatableAddress): 0xA0 +; SYMS64-NEXT: Section: .data +; SYMS64-NEXT: Type: 0x0 +; SYMS64-NEXT: StorageClass: C_EXT (0x2) +; SYMS64-NEXT: NumberOfAuxEntries: 1 +; SYMS64-NEXT: CSECT Auxiliary Entry { +; SYMS64-NEXT: Index: 12 +; SYMS64-NEXT: SectionLen: 24 +; SYMS64-NEXT: ParameterHashIndex: 0x0 +; SYMS64-NEXT: TypeChkSectNum: 0x0 +; SYMS64-NEXT: SymbolAlignmentLog2: 3 +; SYMS64-NEXT: SymbolType: XTY_SD (0x1) +; SYMS64-NEXT: StorageMappingClass: XMC_DS (0xA) +; SYMS64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; SYMS64-NEXT: } +; SYMS64-NEXT: } + +; DUMP64: Sections: +; DUMP64-NEXT: Idx Name Size VMA Type +; DUMP64-NEXT: 0 .text 00000084 0000000000000000 TEXT +; DUMP64-NEXT: 1 .data 00000030 0000000000000088 DATA +; DUMP64-NEXT: 2 .except 00000032 0000000000000000 diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-64bit.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-64bit.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations-64bit.ll @@ -0,0 +1,45 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: --ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; 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 + +; llc filetype=obj tested in /llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section.ll + +!1 = !{!"ppc-trap-reason", !"1", !"2"} +declare void @llvm.ppc.trapd(i64 %a) +declare void @llvm.ppc.tdw(i64 %a, i64 %b, i32 immarg) + +define dso_local void @test__trapd_annotation(i64 %a) { +; CHECK-LABEL: test__trapd_annotation: +; CHECK: # %bb.0: +; CHECK-NEXT: tdi 4, r3, 0 +; CHECK-NEXT: blr +; +; AIX-LABEL: test__trapd_annotation: +; AIX: # %bb.0: +; AIX-NEXT: .except .test__trapd_annotation, 1, 2 +; AIX-NEXT: tdi 4, r3, 0 +; AIX-NEXT: blr + call void @llvm.ppc.trapd(i64 %a), !annotation !1 + ret void +} + +define dso_local void @test__tdw_annotation(i64 %a) { +; CHECK-LABEL: test__tdw_annotation: +; CHECK: # %bb.0: +; CHECK-NEXT: tdi 0, r3, 4 +; CHECK-NEXT: blr +; +; AIX-LABEL: test__tdw_annotation: +; AIX: # %bb.0: +; AIX-NEXT: .except .test__tdw_annotation, 1, 2 +; AIX-NEXT: tdi 0, r3, 4 +; AIX-NEXT: blr + call void @llvm.ppc.tdw(i64 4, i64 %a, i32 0), !annotation !1 + ret void +} diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-trap-annotations.ll @@ -0,0 +1,44 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: --ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \ +; 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 + +; llc filetype=obj tested in /llvm/test/CodeGen/PowerPC/aix-xcoff-exception-section.ll + +!1 = !{!"ppc-trap-reason", !"1", !"2"} +declare void @llvm.ppc.trap(i32 %a) +declare void @llvm.ppc.tw(i32 %a, i32 %b, i32 immarg) +define dso_local void @test__trap_annotation(i32 %a) { +; CHECK-LABEL: test__trap_annotation: +; CHECK: # %bb.0: +; CHECK-NEXT: twi 4, r3, 0 +; CHECK-NEXT: blr +; +; AIX-LABEL: test__trap_annotation: +; AIX: # %bb.0: +; AIX-NEXT: .except .test__trap_annotation, 1, 2 +; AIX-NEXT: twi 4, r3, 0 +; AIX-NEXT: blr + call void @llvm.ppc.trap(i32 %a), !annotation !1 + ret void +} + +define dso_local void @test__tw_annotation(i32 %a) { +; CHECK-LABEL: test__tw_annotation: +; CHECK: # %bb.0: +; CHECK-NEXT: twi 0, r3, 4 +; CHECK-NEXT: blr +; +; AIX-LABEL: test__tw_annotation: +; AIX: # %bb.0: +; AIX-NEXT: .except .test__tw_annotation, 1, 2 +; AIX-NEXT: twi 0, r3, 4 +; AIX-NEXT: blr + call void @llvm.ppc.tw(i32 4, i32 %a, i32 0), !annotation !1 + ret void +}