ARM: support high registers in __builtin_longjmp on WoA

Windows on ARM uses a pure thumb-2 environment.  This means that it can select a
high register when doing a __builtin_longjmp.  We would use a tLDRi which would
truncate the register to a low register.  Use a t2LDRi12 to get the full
register file access.  Tweak the code to just load into PC, as that is an
interworking branch on all supported cores anyways.

llvm-svn: 274815
This commit is contained in:
Saleem Abdulrasool 2016-07-08 00:48:22 +00:00
parent c61723f73e
commit eb059b0e0a
3 changed files with 37 additions and 9 deletions

View File

@ -1882,8 +1882,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
.addReg(0));
return;
}
case ARM::tInt_eh_sjlj_longjmp:
case ARM::tInt_WIN_eh_sjlj_longjmp: {
case ARM::tInt_eh_sjlj_longjmp: {
// ldr $scratch, [$src, #8]
// mov sp, $scratch
// ldr $scratch, [$src, #4]
@ -1918,7 +1917,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
.addReg(0));
EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
.addReg(Opc == ARM::tInt_WIN_eh_sjlj_longjmp ? ARM::R11 : ARM::R7)
.addReg(ARM::R7)
.addReg(SrcReg)
.addImm(0)
// Predicate.
@ -1932,6 +1931,36 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
.addReg(0));
return;
}
case ARM::tInt_WIN_eh_sjlj_longjmp: {
// ldr.w r11, [$src, #0]
// ldr.w sp, [$src, #8]
// ldr.w pc, [$src, #4]
unsigned SrcReg = MI->getOperand(0).getReg();
EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)
.addReg(ARM::R11)
.addReg(SrcReg)
.addImm(0)
// Predicate
.addImm(ARMCC::AL)
.addReg(0));
EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)
.addReg(ARM::SP)
.addReg(SrcReg)
.addImm(8)
// Predicate
.addImm(ARMCC::AL)
.addReg(0));
EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)
.addReg(ARM::PC)
.addReg(SrcReg)
.addImm(4)
// Predicate
.addImm(ARMCC::AL)
.addReg(0));
return;
}
}
MCInst TmpInst;

View File

@ -648,8 +648,9 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr &MI) const {
case ARM::Int_eh_sjlj_longjmp:
return 16;
case ARM::tInt_eh_sjlj_longjmp:
case ARM::tInt_WIN_eh_sjlj_longjmp:
return 10;
case ARM::tInt_WIN_eh_sjlj_longjmp:
return 12;
case ARM::Int_eh_sjlj_setjmp:
case ARM::Int_eh_sjlj_setjmp_nofp:
return 20;

View File

@ -9,9 +9,7 @@ entry:
}
; CHECK: push.w {r11, lr}
; CHECK: ldr r[[SP:[0-9]+]], [r0, #8]
; CHECK: mov sp, r[[SP]]
; CHECK: ldr r[[PC:[0-9]+]], [r0, #4]
; CHECK: ldr r11, [r0]
; CHECK: bx r[[PC]]
; CHECK: ldr.w r11, [r0]
; CHECK: ldr.w sp, [r0, #8]
; CHECK: ldr.w pc, [r0, #4]