diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 74d471e2c83..f78d5fa5070 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -313,6 +313,30 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Keep stack frames 8-byte aligned. ArgsSize = (ArgsSize+7) & ~7; + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + + //Create local copies for byval args. + SmallVector ByValArgs; + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + ISD::ArgFlagsTy Flags = Outs[i].Flags; + if (!Flags.isByVal()) + continue; + + SDValue Arg = OutVals[i]; + unsigned Size = Flags.getByValSize(); + unsigned Align = Flags.getByValAlign(); + + int FI = MFI->CreateStackObject(Size, Align, false); + SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); + SDValue SizeNode = DAG.getConstant(Size, MVT::i32); + + Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align, + false, //isVolatile, + (Size <= 32), //AlwaysInline if size <= 32 + MachinePointerInfo(), MachinePointerInfo()); + ByValArgs.push_back(FIPtr); + } + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true)); SmallVector, 8> RegsToPass; @@ -320,12 +344,18 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, const unsigned StackOffset = 92; // Walk the register/memloc assignments, inserting copies/loads. - for (unsigned i = 0, realArgIdx = 0, e = ArgLocs.size(); + for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size(); i != e; ++i, ++realArgIdx) { CCValAssign &VA = ArgLocs[i]; SDValue Arg = OutVals[realArgIdx]; + ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; + + //Use local copy if it is a byval arg. + if (Flags.isByVal()) + Arg = ByValArgs[byvalArgIdx++]; + // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); diff --git a/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll b/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll new file mode 100644 index 00000000000..85c16e4684e --- /dev/null +++ b/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll @@ -0,0 +1,18 @@ +;RUN: llc -march=sparc < %s | FileCheck %s + +%struct.foo_t = type { i32, i32, i32 } + +@s = internal unnamed_addr global %struct.foo_t { i32 10, i32 20, i32 30 } + +define i32 @test() nounwind { +entry: +;CHECK: test +;CHECK: st +;CHECK: st +;CHECK: st +;CHECK: bar + %0 = tail call i32 @bar(%struct.foo_t* byval @s) nounwind + ret i32 %0 +} + +declare i32 @bar(%struct.foo_t* byval)