diff options
-rw-r--r-- | lib/Target/MSP430/MSP430CallingConv.td | 3 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430ISelLowering.cpp | 60 | ||||
-rw-r--r-- | test/CodeGen/MSP430/byval.ll | 26 |
3 files changed, 72 insertions, 17 deletions
diff --git a/lib/Target/MSP430/MSP430CallingConv.td b/lib/Target/MSP430/MSP430CallingConv.td index ad27cc9..b448cc4 100644 --- a/lib/Target/MSP430/MSP430CallingConv.td +++ b/lib/Target/MSP430/MSP430CallingConv.td @@ -24,6 +24,9 @@ def RetCC_MSP430 : CallingConv<[ // MSP430 Argument Calling Conventions //===----------------------------------------------------------------------===// def CC_MSP430 : CallingConv<[ + // Pass by value if the byval attribute is given + CCIfByVal<CCPassByVal<2, 2>>, + // Promote i8 arguments to i16. CCIfType<[i8], CCPromoteToType<i16>>, diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index fc677ae..6b6a348 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -357,22 +357,34 @@ MSP430TargetLowering::LowerCCCArguments(SDValue Chain, } else { // Sanity check assert(VA.isMemLoc()); - // Load the argument to a virtual register - unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; - if (ObjSize > 2) { - errs() << "LowerFormalArguments Unhandled argument type: " - << EVT(VA.getLocVT()).getEVTString() - << "\n"; + + SDValue InVal; + ISD::ArgFlagsTy Flags = Ins[i].Flags; + + if (Flags.isByVal()) { + int FI = MFI->CreateFixedObject(Flags.getByValSize(), + VA.getLocMemOffset(), true); + InVal = DAG.getFrameIndex(FI, getPointerTy()); + } else { + // Load the argument to a virtual register + unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; + if (ObjSize > 2) { + errs() << "LowerFormalArguments Unhandled argument type: " + << EVT(VA.getLocVT()).getEVTString() + << "\n"; + } + // Create the frame index object for this incoming parameter... + int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); + + // Create the SelectionDAG nodes corresponding to a load + //from this parameter + SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); + InVal = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), + false, false, false, 0); } - // Create the frame index object for this incoming parameter... - int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); - - // Create the SelectionDAG nodes corresponding to a load - //from this parameter - SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); - InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, - MachinePointerInfo::getFixedStack(FI), - false, false, false, 0)); + + InVals.push_back(InVal); } } @@ -498,9 +510,23 @@ MSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, StackPtr, DAG.getIntPtrConstant(VA.getLocMemOffset())); + SDValue MemOp; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + + if (Flags.isByVal()) { + SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i16); + MemOp = DAG.getMemcpy(Chain, dl, PtrOff, Arg, SizeNode, + Flags.getByValAlign(), + /*isVolatile*/false, + /*AlwaysInline=*/true, + MachinePointerInfo(), + MachinePointerInfo()); + } else { + MemOp = DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo(), + false, false, 0); + } - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, - MachinePointerInfo(),false, false, 0)); + MemOpChains.push_back(MemOp); } } diff --git a/test/CodeGen/MSP430/byval.ll b/test/CodeGen/MSP430/byval.ll new file mode 100644 index 0000000..9dda0a0 --- /dev/null +++ b/test/CodeGen/MSP430/byval.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s | FileCheck %s + +target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16" +target triple = "msp430---elf" + +%struct.Foo = type { i16, i16, i16 } +@foo = global %struct.Foo { i16 1, i16 2, i16 3 }, align 2 + +define i16 @callee(%struct.Foo* byval %f) nounwind { +entry: +; CHECK: callee: +; CHECK: mov.w 2(r1), r15 + %0 = getelementptr inbounds %struct.Foo* %f, i32 0, i32 0 + %1 = load i16* %0, align 2 + ret i16 %1 +} + +define void @caller() nounwind { +entry: +; CHECK: caller: +; CHECK: mov.w &foo+4, 4(r1) +; CHECK-NEXT: mov.w &foo+2, 2(r1) +; CHECK-NEXT: mov.w &foo, 0(r1) + %call = call i16 @callee(%struct.Foo* byval @foo) + ret void +} |