From f903c003416ce49539e3af49e2af375e3fcd25d8 Mon Sep 17 00:00:00 2001 From: Oliver Stannard Date: Tue, 11 Oct 2016 10:06:59 +0000 Subject: [PATCH] [ARM] Fix registers clobbered by SjLj EH on soft-float targets Currently, the Int_eh_sjlj_dispatchsetup intrinsic is marked as clobbering all registers, including floating-point registers that may not be present on the target. This is technically true, as we could get linked against code that does use the FP registers, but that will not actually work, as the soft-float code cannot save and restore the FP registers. SjLj exception handling can only work correctly if either all or none of the code is built for a target with FP registers. Therefore, we can assume that, when Int_eh_sjlj_dispatchsetup is compiled for a soft-float target, it is only going to be linked against other soft-float code, and so only clobbers the general-purpose registers. This allows us to check that no non-savable registers are clobbered when generating the prologue/epilogue. Differential Revision: https://reviews.llvm.org/D25180 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283866 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 9 ++++++++ lib/Target/ARM/ARMBaseRegisterInfo.h | 1 + lib/Target/ARM/ARMCallingConv.td | 1 + lib/Target/ARM/ARMISelLowering.cpp | 6 ++++-- test/CodeGen/ARM/eh-dispcont.ll | 30 ++++++++++++++++++++------ 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 2f8b56032ccd..bc759dbe8ccf 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -131,6 +131,15 @@ ARMBaseRegisterInfo::getTLSCallPreservedMask(const MachineFunction &MF) const { return CSR_iOS_TLSCall_RegMask; } +const uint32_t * +ARMBaseRegisterInfo::getSjLjDispatchPreservedMask(const MachineFunction &MF) const { + const ARMSubtarget &STI = MF.getSubtarget(); + if (!STI.useSoftFloat() && STI.hasVFP2() && !STI.isThumb1Only()) + return CSR_NoRegs_RegMask; + else + return CSR_FPRegs_RegMask; +} + const uint32_t * ARMBaseRegisterInfo::getThisReturnPreservedMask(const MachineFunction &MF, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 06d0f7902417..330e1535e863 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -104,6 +104,7 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo { CallingConv::ID) const override; const uint32_t *getNoPreservedMask() const override; const uint32_t *getTLSCallPreservedMask(const MachineFunction &MF) const; + const uint32_t *getSjLjDispatchPreservedMask(const MachineFunction &MF) const; /// getThisReturnPreservedMask - Returns a call preserved mask specific to the /// case that 'returned' is on an i32 first argument if the calling convention diff --git a/lib/Target/ARM/ARMCallingConv.td b/lib/Target/ARM/ARMCallingConv.td index edb69581b9d3..9c278a52a7ff 100644 --- a/lib/Target/ARM/ARMCallingConv.td +++ b/lib/Target/ARM/ARMCallingConv.td @@ -242,6 +242,7 @@ def RetCC_ARM_AAPCS_VFP : CallingConv<[ //===----------------------------------------------------------------------===// def CSR_NoRegs : CalleeSavedRegs<(add)>; +def CSR_FPRegs : CalleeSavedRegs<(add (sequence "D%u", 0, 31))>; def CSR_AAPCS : CalleeSavedRegs<(add LR, R11, R10, R9, R8, R7, R6, R5, R4, (sequence "D%u", 15, 8))>; diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index ba2c2866a5cf..7623841a8e34 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7865,8 +7865,10 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI, const ARMBaseRegisterInfo &RI = AII->getRegisterInfo(); // Add a register mask with no preserved registers. This results in all - // registers being marked as clobbered. - MIB.addRegMask(RI.getNoPreservedMask()); + // registers being marked as clobbered. This can't work if the dispatch block + // is in a Thumb1 function and is linked with ARM code which uses the FP + // registers, as there is no way to preserve the FP registers in Thumb1 mode. + MIB.addRegMask(RI.getSjLjDispatchPreservedMask(*MF)); bool IsPositionIndependent = isPositionIndependent(); unsigned NumLPads = LPadList.size(); diff --git a/test/CodeGen/ARM/eh-dispcont.ll b/test/CodeGen/ARM/eh-dispcont.ll index e9871aa7dc77..d6d93818a882 100644 --- a/test/CodeGen/ARM/eh-dispcont.ll +++ b/test/CodeGen/ARM/eh-dispcont.ll @@ -1,9 +1,9 @@ -; RUN: llc -mtriple armv7-apple-ios -relocation-model=pic -o - %s | FileCheck %s -check-prefix=ARM-PIC -; RUN: llc -mtriple armv7-apple-ios -relocation-model=static -o - %s | FileCheck %s -check-prefix=ARM-NOPIC -; RUN: llc -mtriple armv7-apple-ios -relocation-model=dynamic-no-pic -o - %s | FileCheck %s -check-prefix=ARM-NOPIC -; RUN: llc -mtriple thumbv6-apple-ios -relocation-model=pic -o - %s | FileCheck %s -check-prefix=THUMB1-PIC -; RUN: llc -mtriple thumbv6-apple-ios -relocation-model=static -o - %s | FileCheck %s -check-prefix=THUMB1-NOPIC -; RUN: llc -mtriple thumbv6-apple-ios -relocation-model=dynamic-no-pic -o - %s | FileCheck %s -check-prefix=THUMB1-NOPIC +; RUN: llc -mtriple armv7-apple-ios -relocation-model=pic -o - %s | FileCheck %s -check-prefix=ARM-PIC -check-prefix=ARM +; RUN: llc -mtriple armv7-apple-ios -relocation-model=static -o - %s | FileCheck %s -check-prefix=ARM-NOPIC -check-prefix=ARM +; RUN: llc -mtriple armv7-apple-ios -relocation-model=dynamic-no-pic -o - %s | FileCheck %s -check-prefix=ARM-NOPIC -check-prefix=ARM +; RUN: llc -mtriple thumbv6-apple-ios -relocation-model=pic -o - %s | FileCheck %s -check-prefix=THUMB1-PIC -check-prefix=THUMB1 +; RUN: llc -mtriple thumbv6-apple-ios -relocation-model=static -o - %s | FileCheck %s -check-prefix=THUMB1-NOPIC -check-prefix=THUMB1 +; RUN: llc -mtriple thumbv6-apple-ios -relocation-model=dynamic-no-pic -o - %s | FileCheck %s -check-prefix=THUMB1-NOPIC -check-prefix=THUMB1 @_ZTIi = external constant i8* @@ -41,6 +41,9 @@ attributes #0 = { ssp } attributes #1 = { nounwind } attributes #2 = { noreturn } +; ARM: vst1.64 +; ARM: vst1.64 + ; ARM-PIC: cxa_throw ; ARM-PIC: trap ; ARM-PIC: adr [[REG1:r[0-9]+]], [[LJTI:.*]] @@ -63,6 +66,18 @@ attributes #2 = { noreturn } ; ARM-NOPIC: .end_data_region ; ARM-NOPIC: [[LABEL]] +; ARM: vld1.64 +; ARM: vld1.64 + +; On Thumb1 targets, we have no way to preserve the floating-point registers. +; If all other code is built for Thumb1 or is built soft-float, this is not a +; problem as the FP regs don't need saving. However, if this code is linked +; against ARM code that uses the FP regs, they won't be restored correctly. We +; don't support this use-case, but have no way to prevent it in the compiler. + +; THUMB1: push {{[^d]*$}} +; THUMB1-NOT: vst + ; THUMB1-PIC: cxa_throw ; THUMB1-PIC: trap ; THUMB1-PIC: adr [[REG1:r[0-9]+]], [[LJTI:.*]] @@ -87,3 +102,6 @@ attributes #2 = { noreturn } ; THUMB1-NOPIC: .long [[LABEL:LBB0_[0-9]]]+1 ; THUMB1-NOPIC: .end_data_region ; THUMB1-NOPIC: [[LABEL]] + +; THUMB1-NOT: vld +; THUMB1: pop {{[^d]*$}}