[PATCH] D70800: Fix AArch64 AAPCS frame record chain

Logan Chien via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 27 23:58:20 PST 2019


logan created this revision.
logan added reviewers: efriedma, sdesmalen, t.p.northover.
Herald added subscribers: llvm-commits, hiraditya, kristof.beyls.
Herald added a project: LLVM.

After the commit r368987 (rG643adb55769e <https://reviews.llvm.org/rG643adb55769ecb12e0377dab60de50def15d2cea>) was landed, the frame record (FP and LR register) may be placed in the middle of a stack frame if a function has both callee-saved general-purpose registers and floating point registers.  This will break the stack unwinders that simply walk through the frame records (based on the guarantee from AAPCS64 "The Frame Pointer" section).  This commit fixes the problem by adding the frame record offset.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70800

Files:
  llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
  llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
  llvm/test/CodeGen/AArch64/framelayout-frame-record.ll


Index: llvm/test/CodeGen/AArch64/framelayout-frame-record.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AArch64/framelayout-frame-record.ll
@@ -0,0 +1,19 @@
+; RUN: llc  < %s -mtriple=aarch64--linux-gnu | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+declare void @escape.i64(i64)
+declare void @escape.double(double)
+
+define void @test_frame_record_offset(i64 %a, i64 %b, double %c, double %d) "no-frame-pointer-elim"="true" {
+; CHECK-LABEL: test_frame_record_offset:
+; CHECK: stp x29, x30, [sp, #[[OFFSET:[0-9]+]]]
+; CHECK: add x29, sp, #[[OFFSET]]
+
+  call void @escape.i64(i64 %a)
+  call void @escape.i64(i64 %b)
+  call void @escape.double(double %c)
+  call void @escape.double(double %d)
+  ret void
+}
Index: llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
===================================================================
--- llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
+++ llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
@@ -126,6 +126,10 @@
   // stack slot.
   unsigned TaggedBasePointerOffset = 0;
 
+  // Offset from SP-at-entry to frame record (i.e. the spilled frame pointer
+  // and link address).
+  int FrameRecordOffset = 0;
+
 public:
   AArch64FunctionInfo() = default;
 
@@ -325,6 +329,13 @@
     TaggedBasePointerOffset = Offset;
   }
 
+  int getFrameRecordOffset() const {
+    return FrameRecordOffset;
+  }
+  void setFrameRecordOffset(int Offset) {
+    FrameRecordOffset = Offset;
+  }
+
 private:
   // Hold the lists of LOHs.
   MILOHContainer LOHContainerSet;
Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -1019,7 +1019,8 @@
 
   if (HasFP) {
     // Only set up FP if we actually need to.
-    int FPOffset = isTargetDarwin(MF) ? (AFI->getCalleeSavedStackSize() - 16) : 0;
+    int FPOffset = isTargetDarwin(MF) ? (AFI->getCalleeSavedStackSize() - 16)
+                                      : AFI->getFrameRecordOffset();
 
     if (CombineSPBump)
       FPOffset += AFI->getLocalStackSize();
@@ -1615,7 +1616,8 @@
   // be able to save any instructions.
   if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) {
     int64_t OffsetToFrameRecord =
-        isTargetDarwin(MF) ? (-(int64_t)AFI->getCalleeSavedStackSize() + 16) : 0;
+        isTargetDarwin(MF) ? (-(int64_t)AFI->getCalleeSavedStackSize() + 16)
+                           : -AFI->getFrameRecordOffset();;
     emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::FP,
                     {OffsetToFrameRecord, MVT::i8},
                     TII, MachineInstr::FrameDestroy, false, NeedsWinCFI);
@@ -2282,6 +2284,13 @@
       std::swap(Reg1, Reg2);
       std::swap(FrameIdxReg1, FrameIdxReg2);
     }
+    if (RPI.Type == RegPairInfo::GPR) {
+      AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
+      if (Reg1 == AArch64::FP)
+        AFI->setFrameRecordOffset((RPI.Offset + 1) * Size);
+      if (RPI.isPaired() && Reg2 == AArch64::FP)
+        AFI->setFrameRecordOffset(RPI.Offset * Size);
+    }
     MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(LdrOpc));
     if (RPI.isPaired()) {
       MIB.addReg(Reg2, getDefRegState(true));


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70800.231355.patch
Type: text/x-patch
Size: 3445 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191128/1a594254/attachment.bin>


More information about the llvm-commits mailing list