From: Roman Divacky Date: Thu, 25 Jul 2013 21:36:47 +0000 (+0000) Subject: PPC32 va_list is an actual structure so va_copy needs to copy the whole X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c3825df87e7485dcff3572b12570e0c474dbc042;p=platform%2Fupstream%2Fllvm.git 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! llvm-svn: 187158 --- diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index fd225cc..abb2be6 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/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/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index 776ad2a..1b728a7 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/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/llvm/test/CodeGen/PowerPC/ppc32-vacopy.ll b/llvm/test/CodeGen/PowerPC/ppc32-vacopy.ll new file mode 100644 index 0000000..bc39412 --- /dev/null +++ b/llvm/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]], {{.*}}