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 @@ -16,6 +16,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/Target/TargetLoweringObjectFile.h" namespace llvm { @@ -229,6 +230,9 @@ ~TargetLoweringObjectFileXCOFF() override = default; static bool ShouldEmitEHBlock(const MachineFunction *MF); + static void emitExceptionInfoTable(const MCSymbol *LSDA, + const MCSymbol *PerSym, AsmPrinter *Asm, + MachineModuleInfo *MMI); static bool ShouldSetSSPCanaryBitInTB(const MachineFunction *MF); static MCSymbol *getEHInfoTableSymbol(const MachineFunction *MF); 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 @@ -23,43 +23,6 @@ AIXException::AIXException(AsmPrinter *A) : DwarfCFIExceptionBase(A) {} -void AIXException::emitExceptionInfoTable(const MCSymbol *LSDA, - const MCSymbol *PerSym) { - // Generate EH Info Table. - // The EH Info Table, aka, 'compat unwind section' on AIX, have the following - // format: struct eh_info_t { - // unsigned version; /* EH info verion 0 */ - // #if defined(__64BIT__) - // char _pad[4]; /* padding */ - // #endif - // unsigned long lsda; /* Pointer to LSDA */ - // unsigned long personality; /* Pointer to the personality routine */ - // } - - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getCompactUnwindSection()); - MCSymbol *EHInfoLabel = - TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(Asm->MF); - Asm->OutStreamer->emitLabel(EHInfoLabel); - - // Version number. - Asm->emitInt32(0); - - const DataLayout &DL = MMI->getModule()->getDataLayout(); - const unsigned PointerSize = DL.getPointerSize(); - - // Add necessary paddings in 64 bit mode. - Asm->OutStreamer->emitValueToAlignment(PointerSize); - - // LSDA location. - Asm->OutStreamer->emitValue(MCSymbolRefExpr::create(LSDA, Asm->OutContext), - PointerSize); - - // Personality routine. - Asm->OutStreamer->emitValue(MCSymbolRefExpr::create(PerSym, Asm->OutContext), - PointerSize); -} - void AIXException::endFunction(const MachineFunction *MF) { if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF)) return; @@ -73,7 +36,8 @@ dyn_cast(F.getPersonalityFn()->stripPointerCasts()); const MCSymbol *PerSym = Asm->TM.getSymbol(Per); - emitExceptionInfoTable(LSDALabel, PerSym); + TargetLoweringObjectFileXCOFF::emitExceptionInfoTable(LSDALabel, PerSym, Asm, + MMI); } } // End of namespace llvm diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfException.h b/llvm/lib/CodeGen/AsmPrinter/DwarfException.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfException.h @@ -91,9 +91,6 @@ }; class LLVM_LIBRARY_VISIBILITY AIXException : public DwarfCFIExceptionBase { - /// This is AIX's compat unwind section, which unwinder would use - /// to find the location of LSDA area and personality rountine. - void emitExceptionInfoTable(const MCSymbol *LSDA, const MCSymbol *PerSym); public: AIXException(AsmPrinter *A); 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 @@ -2188,6 +2188,52 @@ return true; } +/// This is AIX's compat unwind section, which unwinder would use +/// to find the location of LSDA area and personality rountine. +void TargetLoweringObjectFileXCOFF::emitExceptionInfoTable( + const MCSymbol *LSDA, const MCSymbol *PerSym, AsmPrinter *Asm, + MachineModuleInfo *MMI) { + // Generate EH Info Table. + // The EH Info Table, aka, 'compat unwind section' on AIX, have the following + // format: struct eh_info_t { + // unsigned version; /* EH info verion 0 */ + // #if defined(__64BIT__) + // char _pad[4]; /* padding */ + // #endif + // unsigned long lsda; /* Pointer to LSDA */ + // unsigned long personality; /* Pointer to the personality routine */ + // } + + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getCompactUnwindSection()); + MCSymbol *EHInfoLabel = + TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(Asm->MF); + Asm->OutStreamer->emitLabel(EHInfoLabel); + + // Version number. + Asm->emitInt32(0); + + const DataLayout &DL = MMI->getModule()->getDataLayout(); + const unsigned PointerSize = DL.getPointerSize(); + + // Add necessary paddings in 64 bit mode. + Asm->OutStreamer->emitValueToAlignment(PointerSize); + + // LSDA location. + if (LSDA == nullptr) + Asm->OutStreamer->emitIntValue(0, PointerSize); + else + Asm->OutStreamer->emitValue(MCSymbolRefExpr::create(LSDA, Asm->OutContext), + PointerSize); + + // Personality routine. + if (PerSym == nullptr) + Asm->OutStreamer->emitIntValue(0, PointerSize); + else + Asm->OutStreamer->emitValue( + MCSymbolRefExpr::create(PerSym, Asm->OutContext), PointerSize); +} + bool TargetLoweringObjectFileXCOFF::ShouldSetSSPCanaryBitInTB( const MachineFunction *MF) { const Function &F = MF->getFunction(); 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 @@ -203,6 +203,7 @@ DenseMap> GOAliasMap; + uint16_t getNumberOfVRSaved(); void emitTracebackTable(); SmallVector TOCDataGlobalVars; @@ -1908,12 +1909,33 @@ return AsmPrinter::SetupMachineFunction(MF); } +uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() { + // Calculate the number of VRs be saved. + // Vector registers 20 through 31 are marked as reserved and cannot be used + // in the default ABI. + const PPCSubtarget &Subtarget = MF->getSubtarget(); + if (Subtarget.isAIXABI() && Subtarget.hasAltivec() && + TM.getAIXExtendedAltivecABI()) { + const MachineRegisterInfo &MRI = MF->getRegInfo(); + for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg) + if (MRI.isPhysRegModified(Reg)) + // Number of VRs saved. + return PPC::V31 - Reg + 1; + } + return 0; +} + void PPCAIXAsmPrinter::emitFunctionBodyEnd() { if (!TM.getXCOFFTracebackTable()) return; emitTracebackTable(); + + if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) && + (getNumberOfVRSaved() > 0)) + TargetLoweringObjectFileXCOFF::emitExceptionInfoTable(nullptr, nullptr, + this, MMI); } void PPCAIXAsmPrinter::emitTracebackTable() { @@ -2068,7 +2090,10 @@ if (FI->hasVectorParms() || HasVectorInst) SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask; - bool ShouldEmitEHBlock = TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF); + bool ShouldEmitEHBlock = + TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) || + (getNumberOfVRSaved() > 0); + if (ShouldEmitEHBlock) SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask; @@ -2178,26 +2203,17 @@ if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) { uint16_t VRData = 0; - // Calculate the number of VRs be saved. - // Vector registers 20 through 31 are marked as reserved and cannot be used - // in the default ABI. - const PPCSubtarget &Subtarget = MF->getSubtarget(); - if (Subtarget.isAIXABI() && Subtarget.hasAltivec() && - TM.getAIXExtendedAltivecABI()) { - for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg) - if (MRI.isPhysRegModified(Reg)) { - // Number of VRs saved. - VRData |= - ((PPC::V31 - Reg + 1) << TracebackTable::NumberOfVRSavedShift) & - TracebackTable::NumberOfVRSavedMask; - // This bit is supposed to set only when the special register - // VRSAVE is saved on stack. - // However, IBM XL compiler sets the bit when any vector registers - // are saved on the stack. We will follow XL's behavior on AIX - // so that we don't get surprise behavior change for C code. - VRData |= TracebackTable::IsVRSavedOnStackMask; - break; - } + uint16_t NumOfVRSaved = getNumberOfVRSaved(); + if (NumOfVRSaved) { + // Number of VRs saved. + VRData |= (NumOfVRSaved << TracebackTable::NumberOfVRSavedShift) & + TracebackTable::NumberOfVRSavedMask; + // This bit is supposed to set only when the special register + // VRSAVE is saved on stack. + // However, IBM XL compiler sets the bit when any vector registers + // are saved on the stack. We will follow XL's behavior on AIX + // so that we don't get surprise behavior change for C code. + VRData |= TracebackTable::IsVRSavedOnStackMask; } // Set has_varargs. diff --git a/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll --- a/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll +++ b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll @@ -69,7 +69,7 @@ ; COMMON-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed ; COMMON-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved ; COMMON-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 -; COMMON-NEXT: .byte 0x80 # +HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; COMMON-NEXT: .byte 0xc0 # +HasVectorInfo, +HasExtensionTable, NumOfGPRsSaved = 0 ; COMMON-NEXT: .byte 0x00 # NumberOfFixedParms = 0 ; COMMON-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack ; CHECK-ASM-NEXT: .vbyte 4, L..foov0-.foov # Function size @@ -80,4 +80,17 @@ ; COMMON-NEXT: .byte 0x01 # NumOfVectorParams = 0, +HasVMXInstruction ; COMMON-NEXT: .vbyte 4, 0x00000000 # Vector Parameter type = ; COMMON-NEXT: .vbyte 2, 0x0000 # Padding +; COMMON-NEXT: .byte 0x08 # ExtensionTableFlag = TB_EH_INFO +; COMMON-NEXT: .align 2 +; COMMON-NEXT: .vbyte 4, L..C2-TOC[TC0] # EHInfo Table + +; COMMON: .csect .eh_info_table[RW],2 +; COMMON-NEXT:__ehinfo.1: +; COMMON-NEXT: .vbyte 4, 0 +; COMMON-NEXT: .align 2 +; COMMON-NEXT: .vbyte 4, 0 +; COMMON-NEXT: .vbyte 4, 0 ; COMMON-NEXT: # -- End function +; COMMON: .toc +; COMMON: L..C2: +; COMMON-NEXT: .tc __ehinfo.1[TC],__ehinfo.1