Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 43d482a

Browse files
committed
Use R0/R1 instead of R4/R5 for ARM eh_return return values
Returning things in callee-save registers can clobber live variables in functions with catch blocks. I'm not 100% sure how this ever worked. The side effect of this means I had to fix the return behavior of functions which return via eh_return so that they save and restore R0/R1 in addition to the callee-save registers. This is all part of our ARM dwarf EH localmod, but doing this same thing on x86 should fix PR8541. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4171 [email protected] Review URL: https://codereview.chromium.org/1154253004
1 parent c822983 commit 43d482a

File tree

5 files changed

+81
-16
lines changed

5 files changed

+81
-16
lines changed

lib/Target/ARM/ARMBaseRegisterInfo.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/CodeGen/MachineFrameInfo.h"
2525
#include "llvm/CodeGen/MachineFunction.h"
2626
#include "llvm/CodeGen/MachineInstrBuilder.h"
27+
#include "llvm/CodeGen/MachineModuleInfo.h" // @LOCALMOD
2728
#include "llvm/CodeGen/MachineRegisterInfo.h"
2829
#include "llvm/CodeGen/RegisterScavenging.h"
2930
#include "llvm/CodeGen/VirtRegMap.h"
@@ -63,7 +64,14 @@ static unsigned getFramePointerReg(const ARMSubtarget &STI) {
6364
const MCPhysReg*
6465
ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
6566
const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
66-
if (STI.isTargetNaCl()) return CSR_NaCl_SaveList; // @LOCALMOD
67+
// @LOCALMOD-START
68+
// We don't support special calling conventions for NaCl here.
69+
if (STI.isTargetNaCl()) {
70+
if (MF->getMMI().callsEHReturn())
71+
return CSR_NaCl_EHRet_SaveList;
72+
return CSR_NaCl_SaveList;
73+
}
74+
// @LOCALMOD-END
6775

6876
const MCPhysReg *RegList =
6977
STI.isTargetDarwin() ? CSR_iOS_SaveList : CSR_AAPCS_SaveList;

lib/Target/ARM/ARMCallingConv.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,5 @@ def CSR_FIQ : CalleeSavedRegs<(add LR, R11, (sequence "R%u", 7, 0))>;
242242
// NaCl does not save R9, but otherwise uses the same order as AAPCS
243243
def CSR_NaCl : CalleeSavedRegs<(add LR, R11, R10, R8, R7, R6, R5, R4,
244244
(sequence "D%u", 15, 8))>;
245+
def CSR_NaCl_EHRet : CalleeSavedRegs<(add CSR_NaCl, R1, R0)>;
245246
// @LOCALMOD-END

lib/Target/ARM/ARMFrameLowering.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,15 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
966966
isKill = false;
967967
}
968968

969+
// @LOCALMOD-START
970+
// Functions which call EHReturn spill all CSRs plus R0/R1
971+
if ((Reg == ARM::R0 || Reg == ARM::R1) &&
972+
MF.getRegInfo().isLiveIn(Reg)) {
973+
assert(MF.getMMI().callsEHReturn());
974+
isKill = false;
975+
}
976+
// @LOCALMOD-END
977+
969978
if (isKill)
970979
MBB.addLiveIn(Reg);
971980

@@ -1025,6 +1034,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
10251034
while (i != 0) {
10261035
unsigned LastReg = 0;
10271036
bool DeleteRet = false;
1037+
unsigned SkippedPop = 0; // @LOCALMOD
10281038
for (; i != 0; --i) {
10291039
unsigned Reg = CSI[i-1].getReg();
10301040
if (!(Func)(Reg, STI.isTargetDarwin())) continue;
@@ -1033,6 +1043,19 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
10331043
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
10341044
continue;
10351045

1046+
// @LOCALMOD-START
1047+
// Functions which call EHReturn spill all of their CSRs plus R0 and R1,
1048+
// (the EHReturn return value registers). Epilogs which return via
1049+
// EHreturn pop all of them, but epilogs which return via normal return
1050+
// must not restore R0 and R1, as that would clobber the return value.
1051+
if (MF.getMMI().callsEHReturn() &&
1052+
RetOpcode != ARM::ARMeh_return &&
1053+
(Reg == ARM::R0 || Reg == ARM::R1)) {
1054+
SkippedPop++;
1055+
continue;
1056+
}
1057+
// @LOCALMOD-END
1058+
10361059
if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
10371060
STI.hasV5TOps() &&
10381061
!STI.isTargetNaCl() /* @LOCALMOD */) {
@@ -1052,6 +1075,21 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
10521075
Regs.push_back(Reg);
10531076
}
10541077

1078+
// @LOCALMOD-START
1079+
if (SkippedPop) {
1080+
// We need to increment the stack pointer to compensate for the skipped
1081+
// pops. However we cannot directly increment it because the epilog
1082+
// insertion code places the stack pointer restore before the CSR
1083+
// restores; it does this by finding the first instruction that's not a
1084+
// pop. If we put an add here, the restore would go in between the
1085+
// restore of the FP registers and the GPRs, instead of before the FP
1086+
// restore. So use a pop into R12 to adjust SP.
1087+
while(SkippedPop--)
1088+
AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP)
1089+
.addReg(ARM::SP)).addReg(ARM::R12);
1090+
}
1091+
// @LOCALMOD-END
1092+
10551093
if (Regs.empty())
10561094
continue;
10571095
if (Regs.size() > 1 || LdrOpc == 0) {

lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -765,23 +765,16 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
765765
if (!Subtarget->isTargetMachO()) {
766766
// Non-MachO platforms may return values in these registers via the
767767
// personality function.
768-
// @LOCALMOD-START
769-
if (Subtarget->isTargetNaCl()) {
770-
// we use the first caller saved regs here
771-
// c.f.: llvm-gcc/llvm-gcc-4.2/gcc/unwind-dw2.c::uw_install_context
772-
// NOTE: these are related to the _Unwind_PNaClSetResult{0,1} functions
773-
setExceptionPointerRegister(ARM::R4);
774-
setExceptionSelectorRegister(ARM::R5);
775-
776-
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
768+
setExceptionPointerRegister(ARM::R0);
769+
setExceptionSelectorRegister(ARM::R1);
770+
}
777771

778-
setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
779-
} else {
780-
setExceptionPointerRegister(ARM::R0);
781-
setExceptionSelectorRegister(ARM::R1);
782-
}
783-
// @LOCALMOD-END
772+
// @LOCALMOD-START
773+
if (Subtarget->isTargetNaCl()) {
774+
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
775+
setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
784776
}
777+
// @LOCALMOD-END
785778

786779
if (Subtarget->getTargetTriple().isWindowsItaniumEnvironment())
787780
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);

test/CodeGen/ARM/ehreturn.ll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: llc -O0 < %s | FileCheck %s
2+
target datalayout = "e-p:32:32-i64:64-n32"
3+
target triple = "armv7-unknown-nacl-gnueabihf"
4+
5+
declare void @llvm.eh.return.i32(i32, i8*) nounwind
6+
declare void @llvm.eh.unwind.init() nounwind
7+
8+
; CHECK-LABEL: @raise_exception
9+
; CHECK: push {r0, r1, r4, r5, r6, r7, r8, r10, r11, lr}
10+
define i32 @raise_exception(i32 %b) {
11+
entry:
12+
tail call void @llvm.eh.unwind.init()
13+
%a = add i32 %b, 3
14+
%cmp = icmp slt i32 %a, 0
15+
br i1 %cmp, label %normal_ret, label %eh_ret
16+
normal_ret:
17+
; CHECK: ldm sp!, {r12}
18+
; CHECK: ldm sp!, {r12}
19+
; CHECK: pop {r4, r5, r6, r7, r8, r10, r11, lr}
20+
ret i32 %a
21+
eh_ret:
22+
; CHECK: pop {r0, r1, r4, r5, r6, r7, r8, r10, r11, lr}
23+
tail call void @llvm.eh.return.i32(i32 %a, i8* null)
24+
unreachable
25+
}

0 commit comments

Comments
 (0)