summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@freebsd.org>2013-07-25 21:36:47 +0000
committerRoman Divacky <rdivacky@freebsd.org>2013-07-25 21:36:47 +0000
commit6ebf55d811bab50e7f42ee8cec60c125f6fe0cd2 (patch)
tree96010301ba3704305cec3486ec3391d7138709e6
parent3367ed322026a475273dc676896c0d03c1e8102f (diff)
downloadllvm-6ebf55d811bab50e7f42ee8cec60c125f6fe0cd2.tar.gz
llvm-6ebf55d811bab50e7f42ee8cec60c125f6fe0cd2.tar.bz2
llvm-6ebf55d811bab50e7f42ee8cec60c125f6fe0cd2.tar.xz
PPC32 va_list is an actual structure so va_copy needs to copy the whole
structure not just a pointer. This implements that and thus fixes va_copy on PPC32. Fixes #15286. Both bug and patch by Florian Zeitz! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187158 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp22
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h2
-rw-r--r--test/CodeGen/PowerPC/ppc32-vacopy.ll24
3 files changed, 47 insertions, 1 deletions
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index fd225ccad5..abb2be6713 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -280,8 +280,13 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
} else
setOperationAction(ISD::VAARG, MVT::Other, Expand);
+ if (Subtarget->isSVR4ABI() && !isPPC64)
+ // VACOPY is custom lowered with the 32-bit SVR4 ABI.
+ setOperationAction(ISD::VACOPY , MVT::Other, Custom);
+ else
+ setOperationAction(ISD::VACOPY , MVT::Other, Expand);
+
// Use the default implementation.
- setOperationAction(ISD::VACOPY , MVT::Other, Expand);
setOperationAction(ISD::VAEND , MVT::Other, Expand);
setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE , MVT::Other, Custom);
@@ -1650,6 +1655,18 @@ SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG,
false, false, false, 0);
}
+SDValue PPCTargetLowering::LowerVACOPY(SDValue Op, SelectionDAG &DAG,
+ const PPCSubtarget &Subtarget) const {
+ assert(!Subtarget.isPPC64() && "LowerVACOPY is PPC32 only");
+
+ // We have to copy the entire va_list struct:
+ // 2*sizeof(char) + 2 Byte alignment + 2*sizeof(char*) = 12 Byte
+ return DAG.getMemcpy(Op.getOperand(0), Op,
+ Op.getOperand(1), Op.getOperand(2),
+ DAG.getConstant(12, MVT::i32), 8, false, true,
+ MachinePointerInfo(), MachinePointerInfo());
+}
+
SDValue PPCTargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
SelectionDAG &DAG) const {
return Op.getOperand(0);
@@ -5715,6 +5732,9 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::VAARG:
return LowerVAARG(Op, DAG, PPCSubTarget);
+ case ISD::VACOPY:
+ return LowerVACOPY(Op, DAG, PPCSubTarget);
+
case ISD::STACKRESTORE: return LowerSTACKRESTORE(Op, DAG, PPCSubTarget);
case ISD::DYNAMIC_STACKALLOC:
return LowerDYNAMIC_STACKALLOC(Op, DAG, PPCSubTarget);
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index 776ad2a75f..1b728a78cd 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -498,6 +498,8 @@ namespace llvm {
const PPCSubtarget &Subtarget) const;
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget) const;
+ SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG,
+ const PPCSubtarget &Subtarget) const;
SDValue LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget) const;
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG,
diff --git a/test/CodeGen/PowerPC/ppc32-vacopy.ll b/test/CodeGen/PowerPC/ppc32-vacopy.ll
new file mode 100644
index 0000000000..bc394125f1
--- /dev/null
+++ b/test/CodeGen/PowerPC/ppc32-vacopy.ll
@@ -0,0 +1,24 @@
+; RUN: llc -mtriple="powerpc-unknown-linux-gnu" < %s | FileCheck %s
+; PR15286
+
+%va_list = type {i8, i8, i16, i8*, i8*}
+declare void @llvm.va_copy(i8*, i8*)
+
+define void @test_vacopy() nounwind {
+entry:
+ %0 = alloca %va_list
+ %1 = alloca %va_list
+ %2 = bitcast %va_list* %0 to i8*
+ %3 = bitcast %va_list* %1 to i8*
+
+ call void @llvm.va_copy(i8* %3, i8* %2)
+
+ ret void
+}
+; CHECK: test_vacopy:
+; CHECK: lwz [[REG1:[0-9]+]], {{.*}}
+; CHECK: lwz [[REG2:[0-9]+]], {{.*}}
+; CHECK: lwz [[REG3:[0-9]+]], {{.*}}
+; CHECK: stw [[REG1]], {{.*}}
+; CHECK: stw [[REG2]], {{.*}}
+; CHECK: stw [[REG3]], {{.*}}