Bug#880221: llvm-toolchain-4.0: Please add patch to fix stack alignment on sparc64

John Paul Adrian Glaubitz glaubitz at physik.fu-berlin.de
Mon Oct 30 18:16:34 UTC 2017


Source: llvm-toolchain-4.0
Version: 1:4.0.1-8
Severity: normal
Tags: patch
User: debian-sparc at lists.debian.org
Usertags: sparc64

Hi!

While working on bootstrapping rustc for sparc64, Michael Karcher discovered
that LLVM may generate code where the stack alignment on sparc64 is incorrect
which results in rustc segfaulting on sparc64 [1].

Michael created a crude hack which fixed the issue and therefore proved his
theory. James Clarke later came up with a proper patch which he has submitted
upstream [2].

I have tested both Michael's and James' patch and both fix the segfault of
rustc on sparc64. Since Michael's patch does deal with alignment larger
than 4k and may also not fix corrupted stack pointers, we chose to use
James' patch.

I am attaching the patch to this bug report. Could you please include it in
the next upload of the llvm-toolchain-4.0 package?

Thanks,
Adrian

> [1] http://lists.llvm.org/pipermail/llvm-dev/2017-October/118620.html
> [2] https://reviews.llvm.org/D39425

--
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz at debian.org
`. `'   Freie Universitaet Berlin - glaubitz at physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913
-------------- next part --------------
Description: Account for bias in stack readjustment
 While trying to get rust running on Sparc64, I encountered an issue inside
 llvm. For some reason I did not try to hunt down, rustc decides to do
 strict (over-)alignment of some stack frames. At a certain point, it is
 requesting an alignment of 64 bytes. This creates the following sparc
 assembly code in the output from SparcFrameLowering.cpp:

 andn %sp,63,%sp

 This ensures (as intended) that the stack pointer has its low 6 bits
 cleared and is perfectly aligned on 64 bytes. Alas, this does not take
 Sparc64's stack pointer bias into account: The real register value is 2047
 (0x7ff) lower than the effective stack pointer address. As the stack an
 Sparc64 is always 8-byte aligned, the stack pointer register modulo 8 has
 to be 1.

 A crude fix to this is to not mask the lowest bit of the stack pointer
 (which will keep it 0 on Sparc32 and 1 on Sparc64), which I have verified
 to fix a Bus Error in rustc on Sparc64/Linux.
 .
 See: http://lists.llvm.org/pipermail/llvm-dev/2017-October/118620.html
Reported-By: Michael Karcher <debian at mkarcher.dialup.fu-berlin.de>
Author: James Clarke <jrtc27 at jrtc27.com>

---
Origin: upstream
Bug: https://reviews.llvm.org/D39425
Last-Update: 2017-10-30

--- llvm-toolchain-4.0-4.0.1.orig/lib/Target/Sparc/SparcFrameLowering.cpp
+++ llvm-toolchain-4.0-4.0.1/lib/Target/Sparc/SparcFrameLowering.cpp
@@ -88,10 +88,11 @@ void SparcFrameLowering::emitPrologue(Ma
 
   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
   MachineFrameInfo &MFI = MF.getFrameInfo();
+  const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
   const SparcInstrInfo &TII =
-      *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
+      *static_cast<const SparcInstrInfo *>(Subtarget.getInstrInfo());
   const SparcRegisterInfo &RegInfo =
-      *static_cast<const SparcRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
+      *static_cast<const SparcRegisterInfo *>(Subtarget.getRegisterInfo());
   MachineBasicBlock::iterator MBBI = MBB.begin();
   // Debug location must be unknown since the first debug location is used
   // to determine the end of the prologue.
@@ -141,7 +142,7 @@ void SparcFrameLowering::emitPrologue(Ma
 
   // Adds the SPARC subtarget-specific spill area to the stack
   // size. Also ensures target-required alignment.
-  NumBytes = MF.getSubtarget<SparcSubtarget>().getAdjustedFrameSize(NumBytes);
+  NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);
 
   // Finally, ensure that the size is sufficiently aligned for the
   // data on the stack.
@@ -176,9 +177,27 @@ void SparcFrameLowering::emitPrologue(Ma
       .addCFIIndex(CFIIndex);
 
   if (NeedsStackRealignment) {
-    // andn %o6, MaxAlign-1, %o6
+    int64_t Bias = Subtarget.getStackPointerBias();
+    unsigned regUnbiased;
+    if (Bias) {
+      // This clobbers G1 which we always know is available here.
+      regUnbiased = SP::G1;
+      // add %o6, BIAS, %g1
+      BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), regUnbiased)
+        .addReg(SP::O6).addImm(Bias);
+    } else
+      regUnbiased = SP::O6;
+
+    // andn %regUnbiased, MaxAlign-1, %regUnbiased
     int MaxAlign = MFI.getMaxAlignment();
-    BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), SP::O6).addReg(SP::O6).addImm(MaxAlign - 1);
+    BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), regUnbiased)
+      .addReg(regUnbiased).addImm(MaxAlign - 1);
+
+    if (Bias) {
+      // add %o6, -BIAS, %g1
+      BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6)
+        .addReg(regUnbiased).addImm(-Bias);
+    }
   }
 }
 


More information about the Pkg-llvm-team mailing list