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 @@ -61,6 +61,9 @@ } void AIXException::endFunction(const MachineFunction *MF) { + // There is no easy way to access register information in `AIXException` + // class. when ShouldEmitEHBlock is false and VRs are saved, A dumy eh info + // table are emitted in PPCAIXAsmPrinter::emitFunctionBodyEnd. if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF)) return; 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; @@ -1881,12 +1882,53 @@ 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 ShouldEmitEHBlock returns true, then the eh info table + // will be emitted via `AIXException::endFunction`. Otherwise, we + // need to emit a dumy eh info table when VRs are saved. We could not + // consolidate these two places into one because there is no easy way + // to access register information in `AIXException` class. + if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) && + (getNumberOfVRSaved() > 0)) { + // Emit dummy EH Info Table. + OutStreamer->SwitchSection(getObjFileLowering().getCompactUnwindSection()); + MCSymbol *EHInfoLabel = + TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF); + OutStreamer->emitLabel(EHInfoLabel); + + // Version number. + OutStreamer->emitInt32(0); + + const DataLayout &DL = MMI->getModule()->getDataLayout(); + const unsigned PointerSize = DL.getPointerSize(); + // Add necessary paddings in 64 bit mode. + OutStreamer->emitValueToAlignment(PointerSize); + + OutStreamer->emitIntValue(0, PointerSize); + OutStreamer->emitIntValue(0, PointerSize); + } } void PPCAIXAsmPrinter::emitTracebackTable() { @@ -2041,7 +2083,10 @@ if (FI->hasVectorParms() || HasVectorInst) SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask; - bool ShouldEmitEHBlock = TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF); + uint16_t NumOfVRSaved = getNumberOfVRSaved(); + bool ShouldEmitEHBlock = + TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) || NumOfVRSaved > 0; + if (ShouldEmitEHBlock) SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask; @@ -2151,26 +2196,16 @@ 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; - } + 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