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 @@ -395,14 +395,16 @@ // Extended Traceback table flags. enum ExtendedTBTableFlag : uint8_t { - TB_OS1 = 0x80, ///< Reserved for OS use - TB_RESERVED = 0x40, ///< Reserved for compiler - TB_SSP_CANARY = 0x20, ///< stack smasher canary present on stack - TB_OS2 = 0x10, ///< Reserved for OS use - TB_LONGTBTABLE2 = 0x01 ///< Additional tbtable extension exists + TB_OS1 = 0x80, ///< Reserved for OS use. + TB_RESERVED = 0x40, ///< Reserved for compiler. + TB_SSP_CANARY = 0x20, ///< stack smasher canary present on stack. + TB_OS2 = 0x10, ///< Reserved for OS use. + TB_EH_INFO = 0x08, ///< Exception handling info present. + TB_LONGTBTABLE2 = 0x01 ///< Additional tbtable extension exists. }; StringRef getNameForTracebackTableLanguageId(TracebackTable::LanguageID LangId); +SmallString<32> getExtendedTBTableFlagString(uint8_t Flag); } // end namespace XCOFF } // end namespace llvm diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -21,6 +21,7 @@ class GlobalValue; class MachineModuleInfo; +class MachineFunction; class MCContext; class MCExpr; class MCSection; @@ -219,6 +220,10 @@ TargetLoweringObjectFileXCOFF() = default; ~TargetLoweringObjectFileXCOFF() override = default; + static bool ShouldEmitEHBlock(const MachineFunction *MF); + + static MCSymbol *getEHInfoTableSymbol(const MachineFunction *MF); + void Initialize(MCContext &Ctx, const TargetMachine &TM) override; bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, diff --git a/llvm/lib/BinaryFormat/XCOFF.cpp b/llvm/lib/BinaryFormat/XCOFF.cpp --- a/llvm/lib/BinaryFormat/XCOFF.cpp +++ b/llvm/lib/BinaryFormat/XCOFF.cpp @@ -128,4 +128,29 @@ return ParmsType; } +SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) { + SmallString<32> Res; + + if (Flag & ExtendedTBTableFlag::TB_OS1) + Res += "TB_OS1 "; + if (Flag & ExtendedTBTableFlag::TB_RESERVED) + Res += "TB_RESERVED "; + if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY) + Res += "TB_SSP_CANARY "; + if (Flag & ExtendedTBTableFlag::TB_OS2) + Res += "TB_OS2 "; + if (Flag & ExtendedTBTableFlag::TB_EH_INFO) + Res += "TB_EH_INFO "; + if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2) + Res += "TB_LONGTBTABLE2 "; + + // Two of the bits that haven't got used in the mask. + if (Flag & 0x06) + Res += "Unknown "; + + // Pop the last space. + Res.pop_back(); + return Res; +} + #undef RELOC_CASE diff --git a/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp b/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp @@ -13,6 +13,7 @@ #include "DwarfException.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/MC/MCSectionXCOFF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -37,8 +38,8 @@ Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getCompactUnwindSection()); - MCSymbol *EHInfoLabel = MMI->getContext().getOrCreateSymbol( - "__ehinfo." + Twine(Asm->getFunctionNumber())); + MCSymbol *EHInfoLabel = + TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(Asm->MF); Asm->OutStreamer->emitLabel(EHInfoLabel); // Version number. @@ -60,20 +61,16 @@ } void AIXException::endFunction(const MachineFunction *MF) { - const Function &F = MF->getFunction(); - bool HasLandingPads = !MF->getLandingPads().empty(); - const Function *Per = nullptr; - if (F.hasPersonalityFn()) - Per = dyn_cast(F.getPersonalityFn()->stripPointerCasts()); - bool EmitEHBlock = - HasLandingPads || (F.hasPersonalityFn() && - !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && - F.needsUnwindTableEntry()); - - if (!EmitEHBlock) + if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF)) return; const MCSymbol *LSDALabel = emitExceptionTable(); + + const Function &F = MF->getFunction(); + assert(F.hasPersonalityFn() && + "Landingpads are presented, but no personality routine is found."); + const Function *Per = + dyn_cast(F.getPersonalityFn()->stripPointerCasts()); const MCSymbol *PerSym = Asm->TM.getSymbol(Per); emitExceptionInfoTable(LSDALabel, PerSym); diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -2054,6 +2054,29 @@ //===----------------------------------------------------------------------===// // XCOFF //===----------------------------------------------------------------------===// +bool TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock( + const MachineFunction *MF) { + if (!MF->getLandingPads().empty()) + return true; + + const Function &F = MF->getFunction(); + if (!F.hasPersonalityFn() || !F.needsUnwindTableEntry()) + return false; + + const Function *Per = + dyn_cast(F.getPersonalityFn()->stripPointerCasts()); + if (isNoOpWithoutInvoke(classifyEHPersonality(Per))) + return false; + + return true; +} + +MCSymbol * +TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(const MachineFunction *MF) { + return MF->getMMI().getContext().getOrCreateSymbol( + "__ehinfo." + Twine(MF->getFunctionNumber())); +} + MCSymbol * TargetLoweringObjectFileXCOFF::getTargetSymbol(const GlobalValue *GV, const TargetMachine &TM) const { 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 @@ -1881,6 +1881,10 @@ (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1); // Set the 6th byte of mandatory field. + bool ShouldEmitEHBlock = TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF); + if (ShouldEmitEHBlock) + SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask; + uint32_t GPRSaved = 0; // X13 is reserved under 64-bit environment. @@ -1977,6 +1981,35 @@ OutStreamer->AddComment("AllocaUsed"); OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg)); } + + uint8_t ExtensionTableFlag = 0; + if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) { + if (ShouldEmitEHBlock) + ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO; + + CommentOS << "ExtensionTableFlag = " + << getExtendedTBTableFlagString(ExtensionTableFlag); + EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag)); + } + + if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) { + auto &Ctx = OutStreamer->getContext(); + MCSymbol *EHInfoSym = + TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF); + MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym); + const MCSymbol *TOCBaseSym = + cast(getObjFileLowering().getTOCBaseSection()) + ->getQualNameSymbol(); + const MCExpr *Exp = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCEntry, Ctx), + MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx); + + const DataLayout &DL = getDataLayout(); + OutStreamer->emitValueToAlignment(4); + OutStreamer->AddComment("EHInfo Table"); + OutStreamer->emitValue(Exp, DL.getPointerSize()); + } + #undef GENBOOLCOMMENT #undef GENVALUECOMMENT } diff --git a/llvm/test/CodeGen/PowerPC/aix-exception.ll b/llvm/test/CodeGen/PowerPC/aix-exception.ll --- a/llvm/test/CodeGen/PowerPC/aix-exception.ll +++ b/llvm/test/CodeGen/PowerPC/aix-exception.ll @@ -98,6 +98,29 @@ ; ASM: bl .__cxa_end_catch[PR] ; ASM: nop ; ASM: b L..BB1_2 + +; ASM: L.._Z9catchFuncv0: +; ASM: .vbyte 4, 0x00000000 # Traceback table begin +; ASM: .byte 0x00 # Version = 0 +; ASM: .byte 0x09 # Language = CPlusPlus +; ASM: .byte 0x22 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; ASM: # +HasTraceBackTableOffset, -IsInternalProcedure +; ASM: # -HasControlledStorage, -IsTOCless +; ASM: # +IsFloatingPointPresent +; ASM: # -IsFloatingPointOperationLogOrAbortEnabled +; ASM: .byte 0x41 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; ASM: # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved +; ASM: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; ASM: .byte 0x40 # -HasVectorInfo, +HasExtensionTable, NumOfGPRsSaved = 0 +; ASM: .byte 0x00 # NumberOfFixedParms = 0 +; ASM: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; ASM: .vbyte 4, L.._Z9catchFuncv0-._Z9catchFuncv # Function size +; ASM: .vbyte 2, 0x000d # Function name len = 13 +; ASM: .byte '_,'Z,'9,'c,'a,'t,'c,'h,'F,'u,'n,'c,'v # Function Name +; ASM: .byte 0x08 # ExtensionTableFlag = TB_EH_INFO +; ASM: .align 2 +; ASM32: .vbyte 4, L..C1-TOC[TC0] # EHInfo Table +; ASM64: .vbyte 8, L..C1-TOC[TC0] # EHInfo Table ; ASM: L..func_end0: ; ASM: .csect .gcc_except_table[RO],2 @@ -129,6 +152,7 @@ ; ASM64: .vbyte 8, L..C0-TOC[TC0] # TypeInfo 1 ; ASM: L..ttbase0: ; ASM: .align 2 + ; ASM: .csect .eh_info_table[RW],2 ; ASM: __ehinfo.1: ; ASM: .vbyte 4, 0 @@ -142,6 +166,8 @@ ; ASM: .toc ; ASM: L..C0: ; ASM: .tc _ZTIi[TC],_ZTIi[UA] +; ASM: L..C1: +; ASM: .tc __ehinfo.1[TC],__ehinfo.1 declare i8* @__cxa_allocate_exception(i32) declare void @__cxa_throw(i8*, i8*, i8*)