Add support for 64-bit calling convention.

This is far from complete, but it is enough to make it possible to write
test cases using i64 arguments.

Missing features:
- Floating point arguments.
- Receiving arguments on the stack.
- Calls.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178523 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2013-04-02 04:09:02 +00:00
parent fcb25e60f5
commit f37812e906
5 changed files with 123 additions and 12 deletions

View File

@ -22,6 +22,14 @@ def RetCC_Sparc32 : CallingConv<[
CCIfType<[f64], CCAssignToReg<[D0, D1]>>
]>;
// Sparc 64-bit C return-value convention.
def RetCC_Sparc64 : CallingConv<[
CCIfType<[i32], CCPromoteToType<i64>>,
CCIfType<[i64], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>,
CCIfType<[f64], CCAssignToReg<[D0, D1]>>
]>;
// Sparc 32-bit C Calling convention.
def CC_Sparc32 : CallingConv<[
//Custom assign SRet to [sp+64].
@ -34,3 +42,15 @@ def CC_Sparc32 : CallingConv<[
// Alternatively, they are assigned to the stack in 4-byte aligned units.
CCAssignToStack<4, 4>
]>;
// Sparc 64-bit C Calling convention.
def CC_Sparc64 : CallingConv<[
// All integers are promoted to i64 by the caller.
CCIfType<[i32], CCPromoteToType<i64>>,
// Integer arguments get passed in integer registers if there is space.
CCIfType<[i64], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
// FIXME: Floating point arguments.
// Alternatively, they are assigned to the stack in 8-byte aligned units.
CCAssignToStack<8, 8>
]>;

View File

@ -93,7 +93,8 @@ SparcTargetLowering::LowerReturn(SDValue Chain,
DAG.getTarget(), RVLocs, *DAG.getContext());
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32);
CCInfo.AnalyzeReturn(Outs, Subtarget->is64Bit() ?
RetCC_Sparc64 : RetCC_Sparc32);
SDValue Flag;
SmallVector<SDValue, 4> RetOps(1, Chain);
@ -138,18 +139,32 @@ SparcTargetLowering::LowerReturn(SDValue Chain,
&RetOps[0], RetOps.size());
}
/// LowerFormalArguments - V8 uses a very simple ABI, where all values are
SDValue SparcTargetLowering::
LowerFormalArguments(SDValue Chain,
CallingConv::ID CallConv,
bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc DL,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const {
if (Subtarget->is64Bit())
return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins,
DL, DAG, InVals);
return LowerFormalArguments_32(Chain, CallConv, IsVarArg, Ins,
DL, DAG, InVals);
}
/// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are
/// passed in either one or two GPRs, including FP values. TODO: we should
/// pass FP values in FP registers for fastcc functions.
SDValue
SparcTargetLowering::LowerFormalArguments(SDValue Chain,
CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals)
const {
SDValue SparcTargetLowering::
LowerFormalArguments_32(SDValue Chain,
CallingConv::ID CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
@ -341,6 +356,63 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain,
return Chain;
}
// Lower formal arguments for the 64 bit ABI.
SDValue SparcTargetLowering::
LowerFormalArguments_64(SDValue Chain,
CallingConv::ID CallConv,
bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc DL,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
// Analyze arguments according to CC_Sparc64.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(),
getTargetMachine(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc64);
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
if (VA.isRegLoc()) {
// This argument is passed in a register.
// All integer register arguments are promoted by the caller to i64.
// Create a virtual register for the promoted live-in value.
unsigned VReg = MF.addLiveIn(VA.getLocReg(),
getRegClassFor(VA.getLocVT()));
SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT());
// The caller promoted the argument, so insert an Assert?ext SDNode so we
// won't promote the value again in this function.
switch (VA.getLocInfo()) {
case CCValAssign::SExt:
Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg,
DAG.getValueType(VA.getValVT()));
break;
case CCValAssign::ZExt:
Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg,
DAG.getValueType(VA.getValVT()));
break;
default:
break;
}
// Truncate the register down to the argument type.
if (VA.isExtInLoc())
Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg);
InVals.push_back(Arg);
continue;
}
// The registers are exhausted. This argument was passed on the stack.
assert(VA.isMemLoc());
}
return Chain;
}
SDValue
SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const {

View File

@ -77,6 +77,18 @@ namespace llvm {
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const;
SDValue LowerFormalArguments_32(SDValue Chain,
CallingConv::ID CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const;
SDValue LowerFormalArguments_64(SDValue Chain,
CallingConv::ID CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const;
virtual SDValue
LowerCall(TargetLowering::CallLoweringInfo &CLI,

View File

@ -0,0 +1,7 @@
; RUN: llc < %s -march=sparcv9 | FileCheck %s
; CHECK: ret2:
; CHECK: or %g0, %i1, %i0
define i64 @ret2(i64 %a, i64 %b) {
ret i64 %b
}

View File

@ -1,5 +1,5 @@
; RUN: llc < %s -march=sparc -mattr=-v9 | not grep popc
; RUN: llc < %s -march=sparcv9 -mattr=v9 | grep popc
; RUN: llc < %s -march=sparc -mattr=+v9 | grep popc
declare i32 @llvm.ctpop.i32(i32)