1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[ARM] Fix PR35379 - incorrect unwind information when compiling with -Oz

The patch makes the unwind information not mention registers, which were pushed
solely for the purpose of saving stack adjustment instructions.

Differential revision: https://reviews.llvm.org/D41300
Fixes https://bugs.llvm.org/show_bug.cgi?id=35379

llvm-svn: 321996
This commit is contained in:
Momchil Velikov 2018-01-08 14:47:19 +00:00
parent d73719cbbe
commit b56f278e08
3 changed files with 72 additions and 4 deletions

View File

@ -1086,6 +1086,8 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
unsigned StartOp = 2 + 2;
// Use all the operands.
unsigned NumOffset = 0;
// Amount of SP adjustment folded into a push.
unsigned Pad = 0;
switch (Opc) {
default:
@ -1107,6 +1109,16 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
// temporary to workaround PR11902.
if (MO.isImplicit())
continue;
// Registers, pushed as a part of folding an SP update into the
// push instruction are marked as undef and should not be
// restored when unwinding, because the function can modify the
// corresponding stack slots.
if (MO.isUndef()) {
assert(RegList.empty() &&
"Pad registers must come before restored ones");
Pad += 4;
continue;
}
RegList.push_back(MO.getReg());
}
break;
@ -1118,8 +1130,12 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
RegList.push_back(SrcReg);
break;
}
if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);
// Account for the SP adjustment, folded into the push.
if (Pad)
ATS.emitPad(Pad);
}
} else {
// Changes of stack / frame pointer.
if (SrcReg == ARM::SP) {

View File

@ -2277,9 +2277,9 @@ bool llvm::tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget,
--CurRegEnc) {
unsigned CurReg = RegClass->getRegister(CurRegEnc);
if (!IsPop) {
// Pushing any register is completely harmless, mark the
// register involved as undef since we don't care about it in
// the slightest.
// Pushing any register is completely harmless, mark the register involved
// as undef since we don't care about its value and must not restore it
// during stack unwinding.
RegList.push_back(MachineOperand::CreateReg(CurReg, false, false,
false, false, true));
--RegsNeeded;

View File

@ -0,0 +1,52 @@
; RUN: llc -mtriple=armv7a-eabi < %s | FileCheck %s --check-prefix=CHECK-ARM
; RUN: llc -mtriple=armv6m-eabi < %s | FileCheck %s --check-prefix=CHECK-THM
; Function Attrs: minsize optsize
declare void @g(i32*) local_unnamed_addr #0
; Function Attrs: minsize optsize
define void @f() local_unnamed_addr #0 {
entry:
%i = alloca i32, align 4
%0 = bitcast i32* %i to i8*
store i32 1, i32* %i, align 4
call void @g(i32* nonnull %i)
ret void
}
; Check unwind info does not mention the registers used for padding, and
; the amount of stack adjustment is the same as in the actual
; instructions.
; CHECK-ARM: .save {r11, lr}
; CHECK-ARM-NEXT: .pad #8
; CHECK-ARM-NEXT: push {r9, r10, r11, lr}
; CHECK-ARM: pop {r2, r3, r11, pc}
; CHECK-THM: .save {r7, lr}
; CHECK-THM-NEXT: .pad #8
; CHECK-THM-NEXT: push {r5, r6, r7, lr}
; CHECK-THM: pop {r2, r3, r7, pc}
define void @f1() local_unnamed_addr #1 {
entry:
%i = alloca i32, align 4
%0 = bitcast i32* %i to i8*
store i32 1, i32* %i, align 4
call void @g(i32* nonnull %i)
ret void
}
; Check that unwind info is the same whether or not using -Os (minsize attr)
; CHECK-ARM: .save {r11, lr}
; CHECK-ARM-NEXT: push {r11, lr}
; CHECK-ARM-NEXT: .pad #8
; CHECK-THM: .save {r7, lr}
; CHECK-THM-NEXT: push {r7, lr}
; CHECK-THM-NEXT: .pad #8
attributes #0 = { minsize optsize }
attributes #1 = { optsize }