Implement support for byval arguments in Sparc backend.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123974 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Venkatraman Govindaraju 2011-01-21 14:00:01 +00:00
parent e7c85a4c1d
commit 46713296e0
2 changed files with 49 additions and 1 deletions

View File

@ -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<SDValue, 8> 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<std::pair<unsigned, SDValue>, 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!");

View File

@ -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)