[PATCH] D109129: [ARM] Fix operands of `Int_eh_sjlj_longjmp`

Tee KOBAYASHI via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 1 21:28:36 PDT 2021


xtkoba created this revision.
Herald added subscribers: hiraditya, kristof.beyls.
xtkoba requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

On Linux, it was made possible by https://reviews.llvm.org/D38253 that `__builtin_longjmp` can jump between ARM mode and Thumb mode. This was done by restoring the saved frame address to each of `r7` and `r11`, the frame pointer register on Linux in Thumb mode and ARM mode, respectively.

However, there has been revealed a case that `__builtin_longjmp` from ARM mode does not work. In that case, `__builtin_longjmp` chooses `r7` for the scratch register, trying to branch to the address contained in it, which has already been overwritten by the saved frame address.

This seems to be not easily worked around on user's side. For example, the compiler option `-fno-omit-frame-pointer` will not prevent `r7` from being used as the scratch register, because it is not the frame pointer register in ARM mode.

In the proposed change, `Int_eh_sjlj_longjmp` is made to use the new register class `GPRnofp` which excludes the potential frame pointer registers `r7` and `r11`.


https://reviews.llvm.org/D109129

Files:
  llvm/lib/Target/ARM/ARMInstrInfo.td
  llvm/lib/Target/ARM/ARMRegisterInfo.td


Index: llvm/lib/Target/ARM/ARMRegisterInfo.td
===================================================================
--- llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -254,6 +254,16 @@
   let DiagnosticString = "operand must be a register in range [r0, r14]";
 }
 
+// GPRs without potential FPs.  Used by eh_sjlj_longjmp().
+def GPRnofp : RegisterClass<"ARM", [i32], 32, (sub GPR, R7, R11)> {
+  let AltOrders = [(add LR, GPRnofp), (trunc GPRnofp, 7),
+                   (add (trunc GPRnofp, 7), R12, LR, (shl GPRnofp, 7))];
+  let AltOrderSelect = [{
+      return MF.getSubtarget<ARMSubtarget>().getGPRAllocationOrder(MF);
+  }];
+  let DiagnosticString = "operand must be a register in range [r0, r15]";
+}
+
 // GPRs without the PC.  Some ARM instructions do not allow the PC in
 // certain operand slots, particularly as the destination.  Primarily
 // useful for disassembly.
Index: llvm/lib/Target/ARM/ARMInstrInfo.td
===================================================================
--- llvm/lib/Target/ARM/ARMInstrInfo.td
+++ llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -5909,10 +5909,10 @@
 
 // FIXME: Non-IOS version(s)
 let isBarrier = 1, hasSideEffects = 1, isTerminator = 1,
-    Defs = [ R7, LR, SP ] in {
-def Int_eh_sjlj_longjmp : PseudoInst<(outs), (ins GPR:$src, GPR:$scratch),
+    Defs = [ R7, R11, LR, SP ] in {
+def Int_eh_sjlj_longjmp : PseudoInst<(outs), (ins GPRnofp:$src, GPRnofp:$scratch),
                              NoItinerary,
-                         [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>,
+                         [(ARMeh_sjlj_longjmp GPRnofp:$src, GPRnofp:$scratch)]>,
                                 Requires<[IsARM]>;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D109129.370152.patch
Type: text/x-patch
Size: 1710 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210902/36bb7cac/attachment.bin>


More information about the llvm-commits mailing list