PPC: Ignore spill/restore requests for VRSAVE (except on Darwin)
authorHal Finkel <hfinkel@anl.gov>
Fri, 28 Jun 2013 22:29:56 +0000 (22:29 +0000)
committerHal Finkel <hfinkel@anl.gov>
Fri, 28 Jun 2013 22:29:56 +0000 (22:29 +0000)
This fixes PR16418, which reports that a function calling
__builtin_unwind_init() asserts. The cause is that this generates a
spill/restore for VRSAVE, and we support that only on Darwin (because VRSAVE is
only really used on Darwin).

The test case checks only that we don't crash. We can add correctness checks
once someone verifies what behavior the function is supposed to have.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185235 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCFrameLowering.cpp
test/CodeGen/PowerPC/unwind-dw2.ll [new file with mode: 0644]

index dc734d1348213dccc99e67f15b963f9ad08d29b7..4c57cf632fb4d099fc316749344691c76e6329ce 100644 (file)
@@ -1145,6 +1145,12 @@ PPCFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
   
   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
     unsigned Reg = CSI[i].getReg();
+    // Only Darwin actually uses the VRSAVE register, but it can still appear
+    // here if, for example, @llvm.eh.unwind.init() is used.  If we're not on
+    // Darwin, ignore it.
+    if (Reg == PPC::VRSAVE && !Subtarget.isDarwinABI())
+      continue;
+
     // CR2 through CR4 are the nonvolatile CR fields.
     bool IsCRField = PPC::CR2 <= Reg && Reg <= PPC::CR4;
 
@@ -1294,6 +1300,12 @@ PPCFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
     unsigned Reg = CSI[i].getReg();
 
+    // Only Darwin actually uses the VRSAVE register, but it can still appear
+    // here if, for example, @llvm.eh.unwind.init() is used.  If we're not on
+    // Darwin, ignore it.
+    if (Reg == PPC::VRSAVE && !Subtarget.isDarwinABI())
+      continue;
+
     if (Reg == PPC::CR2) {
       CR2Spilled = true;
       // The spill slot is associated only with CR2, which is the
diff --git a/test/CodeGen/PowerPC/unwind-dw2.ll b/test/CodeGen/PowerPC/unwind-dw2.ll
new file mode 100644 (file)
index 0000000..e58edff
--- /dev/null
@@ -0,0 +1,15 @@
+; RUN: llc < %s
+target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+; Function Attrs: nounwind
+define void @foo() #0 {
+entry:
+  call void @llvm.eh.unwind.init()
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.eh.unwind.init() #0
+
+attributes #0 = { nounwind }