diff options
author | Saleem Abdulrasool <compnerd@compnerd.org> | 2016-07-08 00:48:22 +0000 |
---|---|---|
committer | Saleem Abdulrasool <compnerd@compnerd.org> | 2016-07-08 00:48:22 +0000 |
commit | eb059b0e0a8337844ad5eb39d74cf2bcbef6ddcf (patch) | |
tree | 3256567fef780ecb170187645983d7dc540bcc27 /llvm/lib/Target/ARM/ARMAsmPrinter.cpp | |
parent | c61723f73e48475fdd31db3f0eca07985580e346 (diff) | |
download | llvm-eb059b0e0a8337844ad5eb39d74cf2bcbef6ddcf.zip llvm-eb059b0e0a8337844ad5eb39d74cf2bcbef6ddcf.tar.gz llvm-eb059b0e0a8337844ad5eb39d74cf2bcbef6ddcf.tar.bz2 |
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
Diffstat (limited to 'llvm/lib/Target/ARM/ARMAsmPrinter.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 8efd937..04863a7 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -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; |