Major calling convention code refactoring.

Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.

This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.

This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2009-08-05 01:29:28 +00:00
parent 518ad1a880
commit 98ca4f2a32
47 changed files with 2080 additions and 2197 deletions

View File

@ -172,17 +172,20 @@ public:
return UsedRegs[Reg/32] & (1 << (Reg&31));
}
/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
/// AnalyzeFormalArguments - Analyze an array of argument values,
/// incorporating info about the formals into this state.
void AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn);
void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
CCAssignFn Fn);
/// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
/// AnalyzeReturn - Analyze the returned values of a return,
/// incorporating info about the result values into this state.
void AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn);
void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
CCAssignFn Fn);
/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
/// about the passed values into this state.
void AnalyzeCallOperands(CallSDNode *TheCall, CCAssignFn Fn);
/// AnalyzeCallOperands - Analyze the outgoing arguments to a call,
/// incorporating info about the passed values into this state.
void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
CCAssignFn Fn);
/// AnalyzeCallOperands - Same as above except it takes vectors of types
/// and argument flags.
@ -190,9 +193,10 @@ public:
SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
CCAssignFn Fn);
/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
/// AnalyzeCallResult - Analyze the return values of a call,
/// incorporating info about the passed values into this state.
void AnalyzeCallResult(CallSDNode *TheCall, CCAssignFn Fn);
void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
CCAssignFn Fn);
/// AnalyzeCallResult - Same as above except it's specialized for calls which
/// produce a single value.

View File

@ -319,7 +319,6 @@ public:
SDValue getExternalSymbol(const char *Sym, DebugLoc dl, MVT VT);
SDValue getTargetExternalSymbol(const char *Sym, MVT VT,
unsigned char TargetFlags = 0);
SDValue getArgFlags(ISD::ArgFlagsTy Flags);
SDValue getValueType(MVT);
SDValue getRegister(unsigned Reg, MVT VT);
SDValue getDbgStopPoint(DebugLoc DL, SDValue Root,
@ -460,6 +459,12 @@ public:
SDValue N1, SDValue N2, SDValue N3, SDValue N4,
SDValue N5);
/// getStackArgumentTokenFactor - Compute a TokenFactor to force all
/// the incoming stack arguments to be loaded from the stack. This is
/// used in tail call lowering to protect stack arguments from being
/// clobbered.
SDValue getStackArgumentTokenFactor(SDValue Chain);
SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool AlwaysInline,
const Value *DstSV, uint64_t DstSVOff,
@ -534,13 +539,6 @@ public:
/// getMergeValues - Create a MERGE_VALUES node from the given operands.
SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl);
/// getCall - Create a CALL node from the given information.
///
SDValue getCall(unsigned CallingConv, DebugLoc dl, bool IsVarArgs,
bool IsTailCall, bool isInreg, SDVTList VTs,
const SDValue *Operands, unsigned NumOperands,
unsigned NumFixedArgs);
/// getLoad - Loads are not normal binary operators: their result type is not
/// determined by their operands, and they produce a value AND a token chain.
///

View File

@ -97,7 +97,7 @@ namespace ISD {
AssertSext, AssertZext,
// Various leaf nodes.
BasicBlock, VALUETYPE, ARG_FLAGS, CONDCODE, Register,
BasicBlock, VALUETYPE, CONDCODE, Register,
Constant, ConstantFP,
GlobalAddress, GlobalTLSAddress, FrameIndex,
JumpTable, ConstantPool, ExternalSymbol,
@ -180,38 +180,6 @@ namespace ISD {
// UNDEF - An undefined node
UNDEF,
/// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG, FLAG0, ..., FLAGn) - This node
/// represents the formal arguments for a function. CC# is a Constant value
/// indicating the calling convention of the function, and ISVARARG is a
/// flag that indicates whether the function is varargs or not. This node
/// has one result value for each incoming argument, plus one for the output
/// chain. It must be custom legalized. See description of CALL node for
/// FLAG argument contents explanation.
///
FORMAL_ARGUMENTS,
/// RV1, RV2...RVn, CHAIN = CALL(CHAIN, CALLEE,
/// ARG0, FLAG0, ARG1, FLAG1, ... ARGn, FLAGn)
/// This node represents a fully general function call, before the legalizer
/// runs. This has one result value for each argument / flag pair, plus
/// a chain result. It must be custom legalized. Flag argument indicates
/// misc. argument attributes. Currently:
/// Bit 0 - signness
/// Bit 1 - 'inreg' attribute
/// Bit 2 - 'sret' attribute
/// Bit 4 - 'byval' attribute
/// Bit 5 - 'nest' attribute
/// Bit 6-9 - alignment of byval structures
/// Bit 10-26 - size of byval structures
/// Bits 31:27 - argument ABI alignment in the first argument piece and
/// alignment '1' in other argument pieces.
///
/// CALL nodes use the CallSDNode subclass of SDNode, which
/// additionally carries information about the calling convention,
/// whether the call is varargs, and if it's marked as a tail call.
///
CALL,
// EXTRACT_ELEMENT - This is used to get the lower or upper (determined by
// a Constant, which is required to be operand #1) half of the integer or
// float value specified as operand #0. This is only for use before
@ -515,12 +483,6 @@ namespace ISD {
// chain, cc, lhs, rhs, block to branch to if condition is true.
BR_CC,
// RET - Return from function. The first operand is the chain,
// and any subsequent operands are pairs of return value and return value
// attributes (see CALL for description of attributes) for the function.
// This operation can have variable number of operands.
RET,
// INLINEASM - Represents an inline asm block. This node always has two
// return values: a chain and a flag result. The inputs are as follows:
// Operand #0 : Input chain.
@ -2234,81 +2196,42 @@ namespace ISD {
/// getRawBits - Represent the flags as a bunch of bits.
uint64_t getRawBits() const { return Flags; }
};
/// InputArg - This struct carries flags and type information about a
/// single incoming (formal) argument or incoming (from the perspective
/// of the caller) return value virtual register.
///
struct InputArg {
ArgFlagsTy Flags;
MVT VT;
bool Used;
InputArg() : VT(MVT::Other), Used(false) {}
InputArg(ISD::ArgFlagsTy flags, MVT vt, bool used)
: Flags(flags), VT(vt), Used(used) {
assert(VT.isSimple() &&
"InputArg value type must be Simple!");
}
};
/// OutputArg - This struct carries flags and a value for a
/// single outgoing (actual) argument or outgoing (from the perspective
/// of the caller) return value virtual register.
///
struct OutputArg {
ArgFlagsTy Flags;
SDValue Val;
bool IsFixed;
OutputArg() : IsFixed(false) {}
OutputArg(ISD::ArgFlagsTy flags, SDValue val, bool isfixed)
: Flags(flags), Val(val), IsFixed(isfixed) {
assert(Val.getValueType().isSimple() &&
"OutputArg value type must be Simple!");
}
};
}
/// ARG_FLAGSSDNode - Leaf node holding parameter flags.
class ARG_FLAGSSDNode : public SDNode {
ISD::ArgFlagsTy TheFlags;
friend class SelectionDAG;
explicit ARG_FLAGSSDNode(ISD::ArgFlagsTy Flags)
: SDNode(ISD::ARG_FLAGS, DebugLoc::getUnknownLoc(),
getSDVTList(MVT::Other)), TheFlags(Flags) {
}
public:
ISD::ArgFlagsTy getArgFlags() const { return TheFlags; }
static bool classof(const ARG_FLAGSSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::ARG_FLAGS;
}
};
/// CallSDNode - Node for calls -- ISD::CALL.
class CallSDNode : public SDNode {
unsigned CallingConv;
bool IsVarArg;
bool IsTailCall;
unsigned NumFixedArgs;
// We might eventually want a full-blown Attributes for the result; that
// will expand the size of the representation. At the moment we only
// need Inreg.
bool Inreg;
friend class SelectionDAG;
CallSDNode(unsigned cc, DebugLoc dl, bool isvararg, bool istailcall,
bool isinreg, SDVTList VTs, const SDValue *Operands,
unsigned numOperands, unsigned numFixedArgs)
: SDNode(ISD::CALL, dl, VTs, Operands, numOperands),
CallingConv(cc), IsVarArg(isvararg), IsTailCall(istailcall),
NumFixedArgs(numFixedArgs), Inreg(isinreg) {}
public:
unsigned getCallingConv() const { return CallingConv; }
unsigned isVarArg() const { return IsVarArg; }
unsigned isTailCall() const { return IsTailCall; }
unsigned isInreg() const { return Inreg; }
/// Set this call to not be marked as a tail call. Normally setter
/// methods in SDNodes are unsafe because it breaks the CSE map,
/// but we don't include the tail call flag for calls so it's ok
/// in this case.
void setNotTailCall() { IsTailCall = false; }
SDValue getChain() const { return getOperand(0); }
SDValue getCallee() const { return getOperand(1); }
unsigned getNumArgs() const { return (getNumOperands() - 2) / 2; }
unsigned getNumFixedArgs() const {
if (isVarArg())
return NumFixedArgs;
else
return getNumArgs();
}
SDValue getArg(unsigned i) const { return getOperand(2+2*i); }
SDValue getArgFlagsVal(unsigned i) const {
return getOperand(3+2*i);
}
ISD::ArgFlagsTy getArgFlags(unsigned i) const {
return cast<ARG_FLAGSSDNode>(getArgFlagsVal(i).getNode())->getArgFlags();
}
unsigned getNumRetVals() const { return getNumValues() - 1; }
MVT getRetValType(unsigned i) const { return getValueType(i); }
static bool classof(const CallSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::CALL;
}
};
/// VTSDNode - This class is used to represent MVT's, which are used
/// to parameterize some operations.
class VTSDNode : public SDNode {
@ -2491,7 +2414,7 @@ typedef LoadSDNode LargestSDNode;
/// MostAlignedSDNode - The SDNode class with the greatest alignment
/// requirement.
///
typedef ARG_FLAGSSDNode MostAlignedSDNode;
typedef GlobalAddressSDNode MostAlignedSDNode;
namespace ISD {
/// isNormalLoad - Returns true if the specified node is a non-extending

View File

@ -1091,16 +1091,27 @@ public:
// the SelectionDAGLowering code knows how to lower these.
//
/// LowerArguments - This hook must be implemented to indicate how we should
/// lower the arguments for the specified function, into the specified DAG.
virtual void
LowerArguments(Function &F, SelectionDAG &DAG,
SmallVectorImpl<SDValue>& ArgValues, DebugLoc dl);
/// LowerFormalArguments - This hook must be implemented to lower the
/// incoming (formal) arguments, described by the Ins array, into the
/// specified DAG. The implementation should fill in the InVals array
/// with legal-type argument values, and return the resulting token
/// chain value.
///
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
assert(0 && "Not Implemented");
return SDValue(); // this is here to silence compiler errors
}
/// LowerCallTo - This hook lowers an abstract call to a function into an
/// LowerCallTo - This function lowers an abstract call to a function into an
/// actual call. This returns a pair of operands. The first element is the
/// return value for the function (if RetTy is not VoidTy). The second
/// element is the outgoing token chain.
/// element is the outgoing token chain. It calls LowerCall to do the actual
/// lowering.
struct ArgListEntry {
SDValue Node;
const Type* Ty;
@ -1116,11 +1127,47 @@ public:
isSRet(false), isNest(false), isByVal(false), Alignment(0) { }
};
typedef std::vector<ArgListEntry> ArgListTy;
virtual std::pair<SDValue, SDValue>
std::pair<SDValue, SDValue>
LowerCallTo(SDValue Chain, const Type *RetTy, bool RetSExt, bool RetZExt,
bool isVarArg, bool isInreg, unsigned NumFixedArgs,
unsigned CallingConv, bool isTailCall, SDValue Callee,
ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl);
unsigned CallConv, bool isTailCall, bool isReturnValueUsed,
SDValue Callee, ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl);
/// LowerCall - This hook must be implemented to lower calls into the
/// the specified DAG. The outgoing arguments to the call are described
/// by the Outs array, and the values to be returned by the call are
/// described by the Ins array. The implementation should fill in the
/// InVals array with legal-type return values from the call, and return
/// the resulting token chain value.
///
/// The isTailCall flag here is normative. If it is true, the
/// implementation must emit a tail call. The
/// IsEligibleForTailCallOptimization hook should be used to catch
/// cases that cannot be handled.
///
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
assert(0 && "Not Implemented");
return SDValue(); // this is here to silence compiler errors
}
/// LowerReturn - This hook must be implemented to lower outgoing
/// return values, described by the Outs array, into the specified
/// DAG. The implementation should return the resulting token chain
/// value.
///
virtual SDValue
LowerReturn(SDValue Chain, unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
assert(0 && "Not Implemented");
return SDValue(); // this is here to silence compiler errors
}
/// EmitTargetCodeForMemcpy - Emit target-specific code that performs a
/// memcpy. This can be used by targets to provide code sequences for cases
@ -1216,19 +1263,17 @@ public:
/// IsEligibleForTailCallOptimization - Check whether the call is eligible for
/// tail call optimization. Targets which want to do tail call optimization
/// should override this function.
virtual bool IsEligibleForTailCallOptimization(CallSDNode *Call,
SDValue Ret,
SelectionDAG &DAG) const {
/// should override this function.
virtual bool
IsEligibleForTailCallOptimization(SDValue Callee,
unsigned CalleeCC,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SelectionDAG& DAG) const {
// Conservative default: no calls are eligible.
return false;
}
/// CheckTailCallReturnConstraints - Check whether CALL node immediatly
/// preceeds the RET node and whether the return uses the result of the node
/// or is a void return. This function can be used by the target to determine
/// eligiblity of tail call optimization.
static bool CheckTailCallReturnConstraints(CallSDNode *TheCall, SDValue Ret);
/// GetPossiblePreceedingTailCall - Get preceeding TailCallNodeOpCode node if
/// it exists. Skip a possible ISD::TokenFactor.
static SDValue GetPossiblePreceedingTailCall(SDValue Chain,

View File

@ -345,7 +345,6 @@ def vsetcc : SDNode<"ISD::VSETCC" , SDTSetCC>;
def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>;
def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>;
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
def ret : SDNode<"ISD::RET" , SDTNone, [SDNPHasChain]>;
def trap : SDNode<"ISD::TRAP" , SDTNone,
[SDNPHasChain, SDNPSideEffect]>;

View File

@ -57,15 +57,16 @@ void CCState::MarkAllocated(unsigned Reg) {
UsedRegs[Reg/32] |= 1 << (Reg&31);
}
/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
/// AnalyzeFormalArguments - Analyze an array of argument values,
/// incorporating info about the formals into this state.
void CCState::AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn) {
unsigned NumArgs = TheArgs->getNumValues()-1;
void
CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
CCAssignFn Fn) {
unsigned NumArgs = Ins.size();
for (unsigned i = 0; i != NumArgs; ++i) {
MVT ArgVT = TheArgs->getValueType(i);
ISD::ArgFlagsTy ArgFlags =
cast<ARG_FLAGSSDNode>(TheArgs->getOperand(3+i))->getArgFlags();
MVT ArgVT = Ins[i].VT;
ISD::ArgFlagsTy ArgFlags = Ins[i].Flags;
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
#ifndef NDEBUG
cerr << "Formal argument #" << i << " has unhandled type "
@ -76,14 +77,14 @@ void CCState::AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn) {
}
}
/// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
/// AnalyzeReturn - Analyze the returned values of a return,
/// incorporating info about the result values into this state.
void CCState::AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn) {
void CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
CCAssignFn Fn) {
// Determine which register each value should be copied into.
for (unsigned i = 0, e = TheRet->getNumOperands() / 2; i != e; ++i) {
MVT VT = TheRet->getOperand(i*2+1).getValueType();
ISD::ArgFlagsTy ArgFlags =
cast<ARG_FLAGSSDNode>(TheRet->getOperand(i*2+2))->getArgFlags();
for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
MVT VT = Outs[i].Val.getValueType();
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)) {
#ifndef NDEBUG
cerr << "Return operand #" << i << " has unhandled type "
@ -95,13 +96,14 @@ void CCState::AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn) {
}
/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
/// about the passed values into this state.
void CCState::AnalyzeCallOperands(CallSDNode *TheCall, CCAssignFn Fn) {
unsigned NumOps = TheCall->getNumArgs();
/// AnalyzeCallOperands - Analyze the outgoing arguments to a call,
/// incorporating info about the passed values into this state.
void CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
CCAssignFn Fn) {
unsigned NumOps = Outs.size();
for (unsigned i = 0; i != NumOps; ++i) {
MVT ArgVT = TheCall->getArg(i).getValueType();
ISD::ArgFlagsTy ArgFlags = TheCall->getArgFlags(i);
MVT ArgVT = Outs[i].Val.getValueType();
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
#ifndef NDEBUG
cerr << "Call operand #" << i << " has unhandled type "
@ -131,14 +133,13 @@ void CCState::AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs,
}
}
/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
/// AnalyzeCallResult - Analyze the return values of a call,
/// incorporating info about the passed values into this state.
void CCState::AnalyzeCallResult(CallSDNode *TheCall, CCAssignFn Fn) {
for (unsigned i = 0, e = TheCall->getNumRetVals(); i != e; ++i) {
MVT VT = TheCall->getRetValType(i);
ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
if (TheCall->isInreg())
Flags.setInReg();
void CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
CCAssignFn Fn) {
for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
MVT VT = Ins[i].VT;
ISD::ArgFlagsTy Flags = Ins[i].Flags;
if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this)) {
#ifndef NDEBUG
cerr << "Call result #" << i << " has unhandled type "

View File

@ -823,11 +823,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
// special case should be done as part of making LegalizeDAG non-recursive.
SimpleFinishLegalizing = false;
break;
case ISD::CALL:
// FIXME: Legalization for calls requires custom-lowering the call before
// legalizing the operands! (I haven't looked into precisely why.)
SimpleFinishLegalizing = false;
break;
case ISD::EXTRACT_ELEMENT:
case ISD::FLT_ROUNDS_:
case ISD::SADDO:
@ -849,7 +844,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
case ISD::TRAMPOLINE:
case ISD::FRAMEADDR:
case ISD::RETURNADDR:
case ISD::FORMAL_ARGUMENTS:
// These operations lie about being legal: when they claim to be legal,
// they should actually be custom-lowered.
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
@ -887,7 +881,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
case ISD::BR_JT:
case ISD::BR_CC:
case ISD::BRCOND:
case ISD::RET:
// Branches tweak the chain to include LastCALLSEQ_END
Ops[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Ops[0],
LastCALLSEQ_END);
@ -951,37 +944,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
cerr << "NODE: "; Node->dump(&DAG); cerr << "\n";
#endif
llvm_unreachable("Do not know how to legalize this operator!");
case ISD::CALL:
// The only option for this is to custom lower it.
Tmp3 = TLI.LowerOperation(Result.getValue(0), DAG);
assert(Tmp3.getNode() && "Target didn't custom lower this node!");
// A call within a calling sequence must be legalized to something
// other than the normal CALLSEQ_END. Violating this gets Legalize
// into an infinite loop.
assert ((!IsLegalizingCall ||
Node->getOpcode() != ISD::CALL ||
Tmp3.getNode()->getOpcode() != ISD::CALLSEQ_END) &&
"Nested CALLSEQ_START..CALLSEQ_END not supported.");
// The number of incoming and outgoing values should match; unless the final
// outgoing value is a flag.
assert((Tmp3.getNode()->getNumValues() == Result.getNode()->getNumValues() ||
(Tmp3.getNode()->getNumValues() == Result.getNode()->getNumValues() + 1 &&
Tmp3.getNode()->getValueType(Tmp3.getNode()->getNumValues() - 1) ==
MVT::Flag)) &&
"Lowering call/formal_arguments produced unexpected # results!");
// Since CALL/FORMAL_ARGUMENTS nodes produce multiple values, make sure to
// remember that we legalized all of them, so it doesn't get relegalized.
for (unsigned i = 0, e = Tmp3.getNode()->getNumValues(); i != e; ++i) {
if (Tmp3.getNode()->getValueType(i) == MVT::Flag)
continue;
Tmp1 = LegalizeOp(Tmp3.getValue(i));
if (Op.getResNo() == i)
Tmp2 = Tmp1;
AddLegalizedOperand(SDValue(Node, i), Tmp1);
}
return Tmp2;
case ISD::BUILD_VECTOR:
switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) {
default: llvm_unreachable("This action is not supported yet!");
@ -1905,7 +1868,9 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node,
const Type *RetTy = Node->getValueType(0).getTypeForMVT();
std::pair<SDValue, SDValue> CallInfo =
TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
0, CallingConv::C, false, Callee, Args, DAG,
0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
Callee, Args, DAG,
Node->getDebugLoc());
// Legalize the call sequence, starting with the chain. This will advance
@ -2311,6 +2276,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
std::pair<SDValue, SDValue> CallResult =
TLI.LowerCallTo(Node->getOperand(0), Type::VoidTy,
false, false, false, false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
DAG.getExternalSymbol("abort", TLI.getPointerTy()),
Args, DAG, dl);
Results.push_back(CallResult.second);

View File

@ -1019,7 +1019,9 @@ SDValue DAGTypeLegalizer::MakeLibCall(RTLIB::Libcall LC, MVT RetVT,
const Type *RetTy = RetVT.getTypeForMVT();
std::pair<SDValue,SDValue> CallInfo =
TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
false, 0, CallingConv::C, false, Callee, Args, DAG, dl);
false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
Callee, Args, DAG, dl);
return CallInfo.first;
}

View File

@ -20,8 +20,8 @@
// type i8 which must be promoted.
//
// This does not legalize vector manipulations like ISD::BUILD_VECTOR,
// or operations that happen to take a vector which are custom-lowered like
// ISD::CALL; the legalization for such operations never produces nodes
// or operations that happen to take a vector which are custom-lowered;
// the legalization for such operations never produces nodes
// with illegal types, so it's okay to put off legalizing them until
// SelectionDAG::Legalize runs.
//

View File

@ -366,9 +366,6 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) {
case ISD::ExternalSymbol:
llvm_unreachable("Should only be used on nodes with operands");
default: break; // Normal nodes don't need extra info.
case ISD::ARG_FLAGS:
ID.AddInteger(cast<ARG_FLAGSSDNode>(N)->getArgFlags().getRawBits());
break;
case ISD::TargetConstant:
case ISD::Constant:
ID.AddPointer(cast<ConstantSDNode>(N)->getConstantIntValue());
@ -430,12 +427,6 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) {
ID.AddInteger(CP->getTargetFlags());
break;
}
case ISD::CALL: {
const CallSDNode *Call = cast<CallSDNode>(N);
ID.AddInteger(Call->getCallingConv());
ID.AddInteger(Call->isVarArg());
break;
}
case ISD::LOAD: {
const LoadSDNode *LD = cast<LoadSDNode>(N);
ID.AddInteger(LD->getMemoryVT().getRawBits());
@ -1103,20 +1094,6 @@ SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) {
return SDValue(N, 0);
}
SDValue SelectionDAG::getArgFlags(ISD::ArgFlagsTy Flags) {
FoldingSetNodeID ID;
AddNodeIDNode(ID, ISD::ARG_FLAGS, getVTList(MVT::Other), 0, 0);
ID.AddInteger(Flags.getRawBits());
void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
return SDValue(E, 0);
SDNode *N = NodeAllocator.Allocate<ARG_FLAGSSDNode>();
new (N) ARG_FLAGSSDNode(Flags);
CSEMap.InsertNode(N, IP);
AllNodes.push_back(N);
return SDValue(N, 0);
}
SDValue SelectionDAG::getValueType(MVT VT) {
if (VT.isSimple() && (unsigned)VT.getSimpleVT() >= ValueTypeNodes.size())
ValueTypeNodes.resize(VT.getSimpleVT()+1);
@ -2995,6 +2972,29 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT,
return getNode(Opcode, DL, VT, Ops, 5);
}
/// getStackArgumentTokenFactor - Compute a TokenFactor to force all
/// the incoming stack arguments to be loaded from the stack.
SDValue SelectionDAG::getStackArgumentTokenFactor(SDValue Chain) {
SmallVector<SDValue, 8> ArgChains;
// Include the original chain at the beginning of the list. When this is
// used by target LowerCall hooks, this helps legalize find the
// CALLSEQ_BEGIN node.
ArgChains.push_back(Chain);
// Add a chain value for each stack argument.
for (SDNode::use_iterator U = getEntryNode().getNode()->use_begin(),
UE = getEntryNode().getNode()->use_end(); U != UE; ++U)
if (LoadSDNode *L = dyn_cast<LoadSDNode>(*U))
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(L->getBasePtr()))
if (FI->getIndex() < 0)
ArgChains.push_back(SDValue(L, 1));
// Build a tokenfactor for all the chains.
return getNode(ISD::TokenFactor, Chain.getDebugLoc(), MVT::Other,
&ArgChains[0], ArgChains.size());
}
/// getMemsetValue - Vectorized representation of the memset value
/// operand.
static SDValue getMemsetValue(SDValue Value, MVT VT, SelectionDAG &DAG,
@ -3386,6 +3386,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst,
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
false, false, false, false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/false,
getExternalSymbol(TLI.getLibcallName(RTLIB::MEMCPY),
TLI.getPointerTy()),
Args, *this, dl);
@ -3433,6 +3434,7 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst,
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
false, false, false, false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/false,
getExternalSymbol(TLI.getLibcallName(RTLIB::MEMMOVE),
TLI.getPointerTy()),
Args, *this, dl);
@ -3486,6 +3488,7 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst,
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
false, false, false, false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/false,
getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET),
TLI.getPointerTy()),
Args, *this, dl);
@ -3615,32 +3618,6 @@ SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList,
return SDValue(N, 0);
}
SDValue
SelectionDAG::getCall(unsigned CallingConv, DebugLoc dl, bool IsVarArgs,
bool IsTailCall, bool IsInreg, SDVTList VTs,
const SDValue *Operands, unsigned NumOperands,
unsigned NumFixedArgs) {
// Do not include isTailCall in the folding set profile.
FoldingSetNodeID ID;
AddNodeIDNode(ID, ISD::CALL, VTs, Operands, NumOperands);
ID.AddInteger(CallingConv);
ID.AddInteger(IsVarArgs);
void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) {
// Instead of including isTailCall in the folding set, we just
// set the flag of the existing node.
if (!IsTailCall)
cast<CallSDNode>(E)->setNotTailCall();
return SDValue(E, 0);
}
SDNode *N = NodeAllocator.Allocate<CallSDNode>();
new (N) CallSDNode(CallingConv, dl, IsVarArgs, IsTailCall, IsInreg,
VTs, Operands, NumOperands, NumFixedArgs);
CSEMap.InsertNode(N, IP);
AllNodes.push_back(N);
return SDValue(N, 0);
}
SDValue
SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl,
ISD::LoadExtType ExtType, MVT VT, SDValue Chain,
@ -5206,7 +5183,6 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::AssertZext: return "AssertZext";
case ISD::BasicBlock: return "BasicBlock";
case ISD::ARG_FLAGS: return "ArgFlags";
case ISD::VALUETYPE: return "ValueType";
case ISD::Register: return "Register";
@ -5254,8 +5230,6 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::EH_LABEL: return "eh_label";
case ISD::DECLARE: return "declare";
case ISD::HANDLENODE: return "handlenode";
case ISD::FORMAL_ARGUMENTS: return "formal_arguments";
case ISD::CALL: return "call";
// Unary operators
case ISD::FABS: return "fabs";
@ -5364,7 +5338,6 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::BR_JT: return "br_jt";
case ISD::BRCOND: return "brcond";
case ISD::BR_CC: return "br_cc";
case ISD::RET: return "ret";
case ISD::CALLSEQ_START: return "callseq_start";
case ISD::CALLSEQ_END: return "callseq_end";
@ -5566,8 +5539,6 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
OS << "<" << M->MO.getValue() << ":" << M->MO.getOffset() << ">";
else
OS << "<null:" << M->MO.getOffset() << ">";
} else if (const ARG_FLAGSSDNode *N = dyn_cast<ARG_FLAGSSDNode>(this)) {
OS << N->getArgFlags().getArgFlagsString();
} else if (const VTSDNode *N = dyn_cast<VTSDNode>(this)) {
OS << ":" << N->getVT().getMVTString();
}

View File

@ -17,6 +17,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Constants.h"
#include "llvm/Constants.h"
#include "llvm/CallingConv.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
@ -753,6 +754,7 @@ void SelectionDAGLowering::clear() {
PendingExports.clear();
DAG.clear();
CurDebugLoc = DebugLoc::getUnknownLoc();
HasTailCall = false;
}
/// getRoot - Return the current virtual root of the Selection DAG,
@ -934,14 +936,8 @@ SDValue SelectionDAGLowering::getValue(const Value *V) {
void SelectionDAGLowering::visitRet(ReturnInst &I) {
if (I.getNumOperands() == 0) {
DAG.setRoot(DAG.getNode(ISD::RET, getCurDebugLoc(),
MVT::Other, getControlRoot()));
return;
}
SmallVector<SDValue, 8> NewValues;
NewValues.push_back(getControlRoot());
SDValue Chain = getControlRoot();
SmallVector<ISD::OutputArg, 8> Outs;
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(TLI, I.getOperand(i)->getType(), ValueVTs);
@ -988,14 +984,16 @@ void SelectionDAGLowering::visitRet(ReturnInst &I) {
else if (F->paramHasAttr(0, Attribute::ZExt))
Flags.setZExt();
for (unsigned i = 0; i < NumParts; ++i) {
NewValues.push_back(Parts[i]);
NewValues.push_back(DAG.getArgFlags(Flags));
}
for (unsigned i = 0; i < NumParts; ++i)
Outs.push_back(ISD::OutputArg(Flags, Parts[i], /*isfixed=*/true));
}
}
DAG.setRoot(DAG.getNode(ISD::RET, getCurDebugLoc(), MVT::Other,
&NewValues[0], NewValues.size()));
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
unsigned CallConv = DAG.getMachineFunction().getFunction()->getCallingConv();
Chain = TLI.LowerReturn(Chain, CallConv, isVarArg,
Outs, getCurDebugLoc(), DAG);
DAG.setRoot(Chain);
}
/// CopyToExportRegsIfNeeded - If the given value has virtual registers
@ -4346,9 +4344,76 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
}
}
/// Test if the given instruction is in a position to be optimized
/// with a tail-call. This roughly means that it's in a block with
/// a return and there's nothing that needs to be scheduled
/// between it and the return.
///
/// This function only tests target-independent requirements.
/// For target-dependent requirements, a target should override
/// TargetLowering::IsEligibleForTailCallOptimization.
///
static bool
isInTailCallPosition(const Instruction *I, Attributes RetAttr,
const TargetLowering &TLI) {
const BasicBlock *ExitBB = I->getParent();
const TerminatorInst *Term = ExitBB->getTerminator();
const ReturnInst *Ret = dyn_cast<ReturnInst>(Term);
const Function *F = ExitBB->getParent();
// The block must end in a return statement or an unreachable.
if (!Ret && !isa<UnreachableInst>(Term)) return false;
// If I will have a chain, make sure no other instruction that will have a
// chain interposes between I and the return.
if (I->mayHaveSideEffects() || I->mayReadFromMemory() ||
!I->isSafeToSpeculativelyExecute())
for (BasicBlock::const_iterator BBI = prior(prior(ExitBB->end())); ;
--BBI) {
if (&*BBI == I)
break;
if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() ||
!BBI->isSafeToSpeculativelyExecute())
return false;
}
// If the block ends with a void return or unreachable, it doesn't matter
// what the call's return type is.
if (!Ret || Ret->getNumOperands() == 0) return true;
// Conservatively require the attributes of the call to match those of
// the return.
if (F->getAttributes().getRetAttributes() != RetAttr)
return false;
// Otherwise, make sure the unmodified return value of I is the return value.
for (const Instruction *U = dyn_cast<Instruction>(Ret->getOperand(0)); ;
U = dyn_cast<Instruction>(U->getOperand(0))) {
if (!U)
return false;
if (!U->hasOneUse())
return false;
if (U == I)
break;
// Check for a truly no-op truncate.
if (isa<TruncInst>(U) &&
TLI.isTruncateFree(U->getOperand(0)->getType(), U->getType()))
continue;
// Check for a truly no-op bitcast.
if (isa<BitCastInst>(U) &&
(U->getOperand(0)->getType() == U->getType() ||
(isa<PointerType>(U->getOperand(0)->getType()) &&
isa<PointerType>(U->getType()))))
continue;
// Otherwise it's not a true no-op.
return false;
}
return true;
}
void SelectionDAGLowering::LowerCallTo(CallSite CS, SDValue Callee,
bool IsTailCall,
bool isTailCall,
MachineBasicBlock *LandingPad) {
const PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
const FunctionType *FTy = cast<FunctionType>(PT->getElementType());
@ -4358,8 +4423,9 @@ void SelectionDAGLowering::LowerCallTo(CallSite CS, SDValue Callee,
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
Args.reserve(CS.arg_size());
unsigned j = 1;
for (CallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();
i != e; ++i) {
i != e; ++i, ++j) {
SDValue ArgNode = getValue(*i);
Entry.Node = ArgNode; Entry.Ty = (*i)->getType();
@ -4385,17 +4451,38 @@ void SelectionDAGLowering::LowerCallTo(CallSite CS, SDValue Callee,
getControlRoot(), BeginLabel));
}
// Check if target-independent constraints permit a tail call here.
// Target-dependent constraints are checked within TLI.LowerCallTo.
if (isTailCall &&
!isInTailCallPosition(CS.getInstruction(),
CS.getAttributes().getRetAttributes(),
TLI))
isTailCall = false;
std::pair<SDValue,SDValue> Result =
TLI.LowerCallTo(getRoot(), CS.getType(),
CS.paramHasAttr(0, Attribute::SExt),
CS.paramHasAttr(0, Attribute::ZExt), FTy->isVarArg(),
CS.paramHasAttr(0, Attribute::InReg), FTy->getNumParams(),
CS.getCallingConv(),
IsTailCall && PerformTailCallOpt,
isTailCall,
!CS.getInstruction()->use_empty(),
Callee, Args, DAG, getCurDebugLoc());
if (CS.getType() != Type::VoidTy)
assert((isTailCall || CS.getType() == Type::VoidTy ||
Result.first.getNode()) &&
"Non-null value expected with non-void non-tail call!");
assert((isTailCall || Result.second.getNode()) &&
"Non-null chain expected with non-tail call!");
assert((Result.second.getNode() || !Result.first.getNode()) &&
"Null value expected with tail call!");
if (Result.first.getNode())
setValue(CS.getInstruction(), Result.first);
DAG.setRoot(Result.second);
// As a special case, a null chain means that a tail call has
// been emitted and the DAG root is already updated.
if (Result.second.getNode())
DAG.setRoot(Result.second);
else
HasTailCall = true;
if (LandingPad && MMI) {
// Insert a label at the end of the invoke call to mark the try range. This
@ -4484,7 +4571,12 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
else
Callee = DAG.getExternalSymbol(RenameFn, TLI.getPointerTy());
LowerCallTo(&I, Callee, I.isTailCall());
// Check if we can potentially perform a tail call. More detailed
// checking is be done within LowerCallTo, after more information
// about the call is known.
bool isTailCall = PerformTailCallOpt && I.isTailCall();
LowerCallTo(&I, Callee, isTailCall);
}
@ -5431,13 +5523,18 @@ void SelectionDAGLowering::visitMalloc(MallocInst &I) {
Entry.Ty = TLI.getTargetData()->getIntPtrType();
Args.push_back(Entry);
bool isTailCall = PerformTailCallOpt &&
isInTailCallPosition(&I, Attribute::None, TLI);
std::pair<SDValue,SDValue> Result =
TLI.LowerCallTo(getRoot(), I.getType(), false, false, false, false,
0, CallingConv::C, PerformTailCallOpt,
0, CallingConv::C, isTailCall,
/*isReturnValueUsed=*/true,
DAG.getExternalSymbol("malloc", IntPtr),
Args, DAG, getCurDebugLoc());
setValue(&I, Result.first); // Pointers always fit in registers
DAG.setRoot(Result.second);
if (Result.first.getNode())
setValue(&I, Result.first); // Pointers always fit in registers
if (Result.second.getNode())
DAG.setRoot(Result.second);
}
void SelectionDAGLowering::visitFree(FreeInst &I) {
@ -5447,12 +5544,16 @@ void SelectionDAGLowering::visitFree(FreeInst &I) {
Entry.Ty = TLI.getTargetData()->getIntPtrType();
Args.push_back(Entry);
MVT IntPtr = TLI.getPointerTy();
bool isTailCall = PerformTailCallOpt &&
isInTailCallPosition(&I, Attribute::None, TLI);
std::pair<SDValue,SDValue> Result =
TLI.LowerCallTo(getRoot(), Type::VoidTy, false, false, false, false,
0, CallingConv::C, PerformTailCallOpt,
0, CallingConv::C, isTailCall,
/*isReturnValueUsed=*/true,
DAG.getExternalSymbol("free", IntPtr), Args, DAG,
getCurDebugLoc());
DAG.setRoot(Result.second);
if (Result.second.getNode())
DAG.setRoot(Result.second);
}
void SelectionDAGLowering::visitVAStart(CallInst &I) {
@ -5486,154 +5587,24 @@ void SelectionDAGLowering::visitVACopy(CallInst &I) {
DAG.getSrcValue(I.getOperand(2))));
}
/// TargetLowering::LowerArguments - This is the default LowerArguments
/// implementation, which just inserts a FORMAL_ARGUMENTS node. FIXME: When all
/// targets are migrated to using FORMAL_ARGUMENTS, this hook should be
/// integrated into SDISel.
void TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &ArgValues,
DebugLoc dl) {
// Add CC# and isVararg as operands to the FORMAL_ARGUMENTS node.
SmallVector<SDValue, 3+16> Ops;
Ops.push_back(DAG.getRoot());
Ops.push_back(DAG.getConstant(F.getCallingConv(), getPointerTy()));
Ops.push_back(DAG.getConstant(F.isVarArg(), getPointerTy()));
// Add one result value for each formal argument.
SmallVector<MVT, 16> RetVals;
unsigned j = 1;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
I != E; ++I, ++j) {
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(*this, I->getType(), ValueVTs);
for (unsigned Value = 0, NumValues = ValueVTs.size();
Value != NumValues; ++Value) {
MVT VT = ValueVTs[Value];
const Type *ArgTy = VT.getTypeForMVT();
ISD::ArgFlagsTy Flags;
unsigned OriginalAlignment =
getTargetData()->getABITypeAlignment(ArgTy);
if (F.paramHasAttr(j, Attribute::ZExt))
Flags.setZExt();
if (F.paramHasAttr(j, Attribute::SExt))
Flags.setSExt();
if (F.paramHasAttr(j, Attribute::InReg))
Flags.setInReg();
if (F.paramHasAttr(j, Attribute::StructRet))
Flags.setSRet();
if (F.paramHasAttr(j, Attribute::ByVal)) {
Flags.setByVal();
const PointerType *Ty = cast<PointerType>(I->getType());
const Type *ElementTy = Ty->getElementType();
unsigned FrameAlign = getByValTypeAlignment(ElementTy);
unsigned FrameSize = getTargetData()->getTypeAllocSize(ElementTy);
// For ByVal, alignment should be passed from FE. BE will guess if
// this info is not there but there are cases it cannot get right.
if (F.getParamAlignment(j))
FrameAlign = F.getParamAlignment(j);
Flags.setByValAlign(FrameAlign);
Flags.setByValSize(FrameSize);
}
if (F.paramHasAttr(j, Attribute::Nest))
Flags.setNest();
Flags.setOrigAlign(OriginalAlignment);
MVT RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT);
for (unsigned i = 0; i != NumRegs; ++i) {
RetVals.push_back(RegisterVT);
ISD::ArgFlagsTy MyFlags = Flags;
if (NumRegs > 1 && i == 0)
MyFlags.setSplit();
// if it isn't first piece, alignment must be 1
else if (i > 0)
MyFlags.setOrigAlign(1);
Ops.push_back(DAG.getArgFlags(MyFlags));
}
}
}
RetVals.push_back(MVT::Other);
// Create the node.
SDNode *Result = DAG.getNode(ISD::FORMAL_ARGUMENTS, dl,
DAG.getVTList(&RetVals[0], RetVals.size()),
&Ops[0], Ops.size()).getNode();
// Prelower FORMAL_ARGUMENTS. This isn't required for functionality, but
// allows exposing the loads that may be part of the argument access to the
// first DAGCombiner pass.
SDValue TmpRes = LowerOperation(SDValue(Result, 0), DAG);
// The number of results should match up, except that the lowered one may have
// an extra flag result.
assert((Result->getNumValues() == TmpRes.getNode()->getNumValues() ||
(Result->getNumValues()+1 == TmpRes.getNode()->getNumValues() &&
TmpRes.getValue(Result->getNumValues()).getValueType() == MVT::Flag))
&& "Lowering produced unexpected number of results!");
// The FORMAL_ARGUMENTS node itself is likely no longer needed.
if (Result != TmpRes.getNode() && Result->use_empty()) {
HandleSDNode Dummy(DAG.getRoot());
DAG.RemoveDeadNode(Result);
}
Result = TmpRes.getNode();
unsigned NumArgRegs = Result->getNumValues() - 1;
DAG.setRoot(SDValue(Result, NumArgRegs));
// Set up the return result vector.
unsigned i = 0;
unsigned Idx = 1;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
++I, ++Idx) {
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(*this, I->getType(), ValueVTs);
for (unsigned Value = 0, NumValues = ValueVTs.size();
Value != NumValues; ++Value) {
MVT VT = ValueVTs[Value];
MVT PartVT = getRegisterType(VT);
unsigned NumParts = getNumRegisters(VT);
SmallVector<SDValue, 4> Parts(NumParts);
for (unsigned j = 0; j != NumParts; ++j)
Parts[j] = SDValue(Result, i++);
ISD::NodeType AssertOp = ISD::DELETED_NODE;
if (F.paramHasAttr(Idx, Attribute::SExt))
AssertOp = ISD::AssertSext;
else if (F.paramHasAttr(Idx, Attribute::ZExt))
AssertOp = ISD::AssertZext;
ArgValues.push_back(getCopyFromParts(DAG, dl, &Parts[0], NumParts,
PartVT, VT, AssertOp));
}
}
assert(i == NumArgRegs && "Argument register count mismatch!");
}
/// TargetLowering::LowerCallTo - This is the default LowerCallTo
/// implementation, which just inserts an ISD::CALL node, which is later custom
/// lowered by the target to something concrete. FIXME: When all targets are
/// migrated to using ISD::CALL, this hook should be integrated into SDISel.
/// implementation, which just calls LowerCall.
/// FIXME: When all targets are
/// migrated to using LowerCall, this hook should be integrated into SDISel.
std::pair<SDValue, SDValue>
TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
bool RetSExt, bool RetZExt, bool isVarArg,
bool isInreg, unsigned NumFixedArgs,
unsigned CallingConv, bool isTailCall,
unsigned CallConv, bool isTailCall,
bool isReturnValueUsed,
SDValue Callee,
ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl) {
assert((!isTailCall || PerformTailCallOpt) &&
"isTailCall set when tail-call optimizations are disabled!");
SmallVector<SDValue, 32> Ops;
Ops.push_back(Chain); // Op#0 - Chain
Ops.push_back(Callee);
// Handle all of the outgoing arguments.
SmallVector<ISD::OutputArg, 32> Outs;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(*this, Args[i].Ty, ValueVTs);
@ -5684,75 +5655,92 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
getCopyToParts(DAG, dl, Op, &Parts[0], NumParts, PartVT, ExtendKind);
for (unsigned i = 0; i != NumParts; ++i) {
for (unsigned j = 0; j != NumParts; ++j) {
// if it isn't first piece, alignment must be 1
ISD::ArgFlagsTy MyFlags = Flags;
if (NumParts > 1 && i == 0)
MyFlags.setSplit();
else if (i != 0)
MyFlags.setOrigAlign(1);
ISD::OutputArg MyFlags(Flags, Parts[j], i < NumFixedArgs);
if (NumParts > 1 && j == 0)
MyFlags.Flags.setSplit();
else if (j != 0)
MyFlags.Flags.setOrigAlign(1);
Ops.push_back(Parts[i]);
Ops.push_back(DAG.getArgFlags(MyFlags));
Outs.push_back(MyFlags);
}
}
}
// Figure out the result value types. We start by making a list of
// the potentially illegal return value types.
SmallVector<MVT, 4> LoweredRetTys;
// Handle the incoming return values from the call.
SmallVector<ISD::InputArg, 32> Ins;
SmallVector<MVT, 4> RetTys;
ComputeValueVTs(*this, RetTy, RetTys);
// Then we translate that to a list of legal types.
for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
MVT VT = RetTys[I];
MVT RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT);
for (unsigned i = 0; i != NumRegs; ++i)
LoweredRetTys.push_back(RegisterVT);
}
LoweredRetTys.push_back(MVT::Other); // Always has a chain.
// Create the CALL node.
SDValue Res = DAG.getCall(CallingConv, dl,
isVarArg, isTailCall, isInreg,
DAG.getVTList(&LoweredRetTys[0],
LoweredRetTys.size()),
&Ops[0], Ops.size(), NumFixedArgs
);
Chain = Res.getValue(LoweredRetTys.size() - 1);
// Gather up the call result into a single value.
if (RetTy != Type::VoidTy && !RetTys.empty()) {
ISD::NodeType AssertOp = ISD::DELETED_NODE;
if (RetSExt)
AssertOp = ISD::AssertSext;
else if (RetZExt)
AssertOp = ISD::AssertZext;
SmallVector<SDValue, 4> ReturnValues;
unsigned RegNo = 0;
for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
MVT VT = RetTys[I];
MVT RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT);
unsigned RegNoEnd = NumRegs + RegNo;
SmallVector<SDValue, 4> Results;
for (; RegNo != RegNoEnd; ++RegNo)
Results.push_back(Res.getValue(RegNo));
SDValue ReturnValue =
getCopyFromParts(DAG, dl, &Results[0], NumRegs, RegisterVT, VT,
AssertOp);
ReturnValues.push_back(ReturnValue);
for (unsigned i = 0; i != NumRegs; ++i) {
ISD::InputArg MyFlags;
MyFlags.VT = RegisterVT;
MyFlags.Used = isReturnValueUsed;
if (RetSExt)
MyFlags.Flags.setSExt();
if (RetZExt)
MyFlags.Flags.setZExt();
if (isInreg)
MyFlags.Flags.setInReg();
Ins.push_back(MyFlags);
}
Res = DAG.getNode(ISD::MERGE_VALUES, dl,
DAG.getVTList(&RetTys[0], RetTys.size()),
&ReturnValues[0], ReturnValues.size());
}
// Check if target-dependent constraints permit a tail call here.
// Target-independent constraints should be checked by the caller.
if (isTailCall &&
!IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg, Ins, DAG))
isTailCall = false;
SmallVector<SDValue, 4> InVals;
Chain = LowerCall(Chain, Callee, CallConv, isVarArg, isTailCall,
Outs, Ins, dl, DAG, InVals);
assert((!isTailCall || InVals.empty()) && "Tail call had return SDValues!");
// For a tail call, the return value is merely live-out and there aren't
// any nodes in the DAG representing it. Return a special value to
// indicate that a tail call has been emitted and no more Instructions
// should be processed in the current block.
if (isTailCall) {
DAG.setRoot(Chain);
return std::make_pair(SDValue(), SDValue());
}
// Collect the legal value parts into potentially illegal values
// that correspond to the original function's return values.
ISD::NodeType AssertOp = ISD::DELETED_NODE;
if (RetSExt)
AssertOp = ISD::AssertSext;
else if (RetZExt)
AssertOp = ISD::AssertZext;
SmallVector<SDValue, 4> ReturnValues;
unsigned CurReg = 0;
for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
MVT VT = RetTys[I];
MVT RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT);
SDValue ReturnValue =
getCopyFromParts(DAG, dl, &InVals[CurReg], NumRegs, RegisterVT, VT,
AssertOp);
ReturnValues.push_back(ReturnValue);
CurReg += NumRegs;
}
// For a function returning void, there is no return value. We can't create
// such a node, so we just return a null return value in that case. In
// that case, nothing will actualy look at the value.
if (ReturnValues.empty())
return std::make_pair(SDValue(), Chain);
SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl,
DAG.getVTList(&RetTys[0], RetTys.size()),
&ReturnValues[0], ReturnValues.size());
return std::make_pair(Res, Chain);
}
@ -5789,25 +5777,108 @@ void SelectionDAGISel::
LowerArguments(BasicBlock *LLVMBB) {
// If this is the entry block, emit arguments.
Function &F = *LLVMBB->getParent();
SDValue OldRoot = SDL->DAG.getRoot();
SmallVector<SDValue, 16> Args;
TLI.LowerArguments(F, SDL->DAG, Args, SDL->getCurDebugLoc());
SelectionDAG &DAG = SDL->DAG;
SDValue OldRoot = DAG.getRoot();
DebugLoc dl = SDL->getCurDebugLoc();
const TargetData *TD = TLI.getTargetData();
unsigned a = 0;
for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end();
AI != E; ++AI) {
// Set up the incoming argument description vector.
SmallVector<ISD::InputArg, 16> Ins;
unsigned Idx = 1;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
I != E; ++I, ++Idx) {
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(TLI, AI->getType(), ValueVTs);
ComputeValueVTs(TLI, I->getType(), ValueVTs);
bool isArgValueUsed = !I->use_empty();
for (unsigned Value = 0, NumValues = ValueVTs.size();
Value != NumValues; ++Value) {
MVT VT = ValueVTs[Value];
const Type *ArgTy = VT.getTypeForMVT();
ISD::ArgFlagsTy Flags;
unsigned OriginalAlignment =
TD->getABITypeAlignment(ArgTy);
if (F.paramHasAttr(Idx, Attribute::ZExt))
Flags.setZExt();
if (F.paramHasAttr(Idx, Attribute::SExt))
Flags.setSExt();
if (F.paramHasAttr(Idx, Attribute::InReg))
Flags.setInReg();
if (F.paramHasAttr(Idx, Attribute::StructRet))
Flags.setSRet();
if (F.paramHasAttr(Idx, Attribute::ByVal)) {
Flags.setByVal();
const PointerType *Ty = cast<PointerType>(I->getType());
const Type *ElementTy = Ty->getElementType();
unsigned FrameAlign = TLI.getByValTypeAlignment(ElementTy);
unsigned FrameSize = TD->getTypeAllocSize(ElementTy);
// For ByVal, alignment should be passed from FE. BE will guess if
// this info is not there but there are cases it cannot get right.
if (F.getParamAlignment(Idx))
FrameAlign = F.getParamAlignment(Idx);
Flags.setByValAlign(FrameAlign);
Flags.setByValSize(FrameSize);
}
if (F.paramHasAttr(Idx, Attribute::Nest))
Flags.setNest();
Flags.setOrigAlign(OriginalAlignment);
MVT RegisterVT = TLI.getRegisterType(VT);
unsigned NumRegs = TLI.getNumRegisters(VT);
for (unsigned i = 0; i != NumRegs; ++i) {
ISD::InputArg MyFlags(Flags, RegisterVT, isArgValueUsed);
if (NumRegs > 1 && i == 0)
MyFlags.Flags.setSplit();
// if it isn't first piece, alignment must be 1
else if (i > 0)
MyFlags.Flags.setOrigAlign(1);
Ins.push_back(MyFlags);
}
}
}
// Call the target to set up the argument values.
SmallVector<SDValue, 8> InVals;
SDValue NewRoot = TLI.LowerFormalArguments(DAG.getRoot(), F.getCallingConv(),
F.isVarArg(), Ins,
dl, DAG, InVals);
DAG.setRoot(NewRoot);
// Set up the argument values.
unsigned i = 0;
Idx = 1;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
++I, ++Idx) {
SmallVector<SDValue, 4> ArgValues;
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(TLI, I->getType(), ValueVTs);
unsigned NumValues = ValueVTs.size();
if (!AI->use_empty()) {
SDL->setValue(AI, SDL->DAG.getMergeValues(&Args[a], NumValues,
SDL->getCurDebugLoc()));
for (unsigned Value = 0; Value != NumValues; ++Value) {
MVT VT = ValueVTs[Value];
MVT PartVT = TLI.getRegisterType(VT);
unsigned NumParts = TLI.getNumRegisters(VT);
if (!I->use_empty()) {
ISD::NodeType AssertOp = ISD::DELETED_NODE;
if (F.paramHasAttr(Idx, Attribute::SExt))
AssertOp = ISD::AssertSext;
else if (F.paramHasAttr(Idx, Attribute::ZExt))
AssertOp = ISD::AssertZext;
ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts,
PartVT, VT, AssertOp));
}
i += NumParts;
}
if (!I->use_empty()) {
SDL->setValue(I, DAG.getMergeValues(&ArgValues[0], NumValues,
SDL->getCurDebugLoc()));
// If this argument is live outside of the entry block, insert a copy from
// whereever we got it to the vreg that other BB's will reference it as.
SDL->CopyToExportRegsIfNeeded(AI);
SDL->CopyToExportRegsIfNeeded(I);
}
a += NumValues;
}
assert(i == InVals.size() && "Argument register count mismatch!");
// Finally, if the target has anything special to do, allow it to do so.
// FIXME: this should insert code into the DAG!

View File

@ -363,13 +363,20 @@ public:
/// GFI - Garbage collection metadata for the function.
GCFunctionInfo *GFI;
/// HasTailCall - This is set to true if a call in the current
/// block has been translated as a tail call. In this case,
/// no subsequent DAG nodes should be created.
///
bool HasTailCall;
LLVMContext *Context;
SelectionDAGLowering(SelectionDAG &dag, TargetLowering &tli,
FunctionLoweringInfo &funcinfo,
CodeGenOpt::Level ol)
: CurDebugLoc(DebugLoc::getUnknownLoc()),
TLI(tli), DAG(dag), FuncInfo(funcinfo), OptLevel(ol),
TLI(tli), DAG(dag), FuncInfo(funcinfo), OptLevel(ol),
HasTailCall(false),
Context(dag.getContext()) {
}

View File

@ -366,140 +366,36 @@ static void copyCatchInfo(BasicBlock *SrcBB, BasicBlock *DestBB,
}
}
/// IsFixedFrameObjectWithPosOffset - Check if object is a fixed frame object and
/// whether object offset >= 0.
static bool
IsFixedFrameObjectWithPosOffset(MachineFrameInfo *MFI, SDValue Op) {
if (!isa<FrameIndexSDNode>(Op)) return false;
FrameIndexSDNode * FrameIdxNode = dyn_cast<FrameIndexSDNode>(Op);
int FrameIdx = FrameIdxNode->getIndex();
return MFI->isFixedObjectIndex(FrameIdx) &&
MFI->getObjectOffset(FrameIdx) >= 0;
}
/// IsPossiblyOverwrittenArgumentOfTailCall - Check if the operand could
/// possibly be overwritten when lowering the outgoing arguments in a tail
/// call. Currently the implementation of this call is very conservative and
/// assumes all arguments sourcing from FORMAL_ARGUMENTS or a CopyFromReg with
/// virtual registers would be overwritten by direct lowering.
static bool IsPossiblyOverwrittenArgumentOfTailCall(SDValue Op,
MachineFrameInfo *MFI) {
RegisterSDNode * OpReg = NULL;
if (Op.getOpcode() == ISD::FORMAL_ARGUMENTS ||
(Op.getOpcode()== ISD::CopyFromReg &&
(OpReg = dyn_cast<RegisterSDNode>(Op.getOperand(1))) &&
(OpReg->getReg() >= TargetRegisterInfo::FirstVirtualRegister)) ||
(Op.getOpcode() == ISD::LOAD &&
IsFixedFrameObjectWithPosOffset(MFI, Op.getOperand(1))) ||
(Op.getOpcode() == ISD::MERGE_VALUES &&
Op.getOperand(Op.getResNo()).getOpcode() == ISD::LOAD &&
IsFixedFrameObjectWithPosOffset(MFI, Op.getOperand(Op.getResNo()).
getOperand(1))))
return true;
return false;
}
/// CheckDAGForTailCallsAndFixThem - This Function looks for CALL nodes in the
/// DAG and fixes their tailcall attribute operand.
static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG,
const TargetLowering& TLI) {
SDNode * Ret = NULL;
SDValue Terminator = DAG.getRoot();
// Find RET node.
if (Terminator.getOpcode() == ISD::RET) {
Ret = Terminator.getNode();
}
// Fix tail call attribute of CALL nodes.
for (SelectionDAG::allnodes_iterator BE = DAG.allnodes_begin(),
BI = DAG.allnodes_end(); BI != BE; ) {
--BI;
if (CallSDNode *TheCall = dyn_cast<CallSDNode>(BI)) {
SDValue OpRet(Ret, 0);
SDValue OpCall(BI, 0);
bool isMarkedTailCall = TheCall->isTailCall();
// If CALL node has tail call attribute set to true and the call is not
// eligible (no RET or the target rejects) the attribute is fixed to
// false. The TargetLowering::IsEligibleForTailCallOptimization function
// must correctly identify tail call optimizable calls.
if (!isMarkedTailCall) continue;
if (Ret==NULL ||
!TLI.IsEligibleForTailCallOptimization(TheCall, OpRet, DAG)) {
// Not eligible. Mark CALL node as non tail call. Note that we
// can modify the call node in place since calls are not CSE'd.
TheCall->setNotTailCall();
} else {
// Look for tail call clobbered arguments. Emit a series of
// copyto/copyfrom virtual register nodes to protect them.
SmallVector<SDValue, 32> Ops;
SDValue Chain = TheCall->getChain(), InFlag;
Ops.push_back(Chain);
Ops.push_back(TheCall->getCallee());
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
SDValue Arg = TheCall->getArg(i);
bool isByVal = TheCall->getArgFlags(i).isByVal();
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
if (!isByVal &&
IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) {
MVT VT = Arg.getValueType();
unsigned VReg = MF.getRegInfo().
createVirtualRegister(TLI.getRegClassFor(VT));
Chain = DAG.getCopyToReg(Chain, Arg.getDebugLoc(),
VReg, Arg, InFlag);
InFlag = Chain.getValue(1);
Arg = DAG.getCopyFromReg(Chain, Arg.getDebugLoc(),
VReg, VT, InFlag);
Chain = Arg.getValue(1);
InFlag = Arg.getValue(2);
}
Ops.push_back(Arg);
Ops.push_back(TheCall->getArgFlagsVal(i));
}
// Link in chain of CopyTo/CopyFromReg.
Ops[0] = Chain;
DAG.UpdateNodeOperands(OpCall, Ops.begin(), Ops.size());
}
}
}
}
void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
BasicBlock::iterator Begin,
BasicBlock::iterator End) {
SDL->setCurrentBasicBlock(BB);
// Lower all of the non-terminator instructions.
for (BasicBlock::iterator I = Begin; I != End; ++I)
// Lower all of the non-terminator instructions. If a call is emitted
// as a tail call, cease emitting nodes for this block.
for (BasicBlock::iterator I = Begin; I != End && !SDL->HasTailCall; ++I)
if (!isa<TerminatorInst>(I))
SDL->visit(*I);
// Ensure that all instructions which are used outside of their defining
// blocks are available as virtual registers. Invoke is handled elsewhere.
for (BasicBlock::iterator I = Begin; I != End; ++I)
if (!isa<PHINode>(I) && !isa<InvokeInst>(I))
SDL->CopyToExportRegsIfNeeded(I);
if (!SDL->HasTailCall) {
// Ensure that all instructions which are used outside of their defining
// blocks are available as virtual registers. Invoke is handled elsewhere.
for (BasicBlock::iterator I = Begin; I != End; ++I)
if (!isa<PHINode>(I) && !isa<InvokeInst>(I))
SDL->CopyToExportRegsIfNeeded(I);
// Handle PHI nodes in successor blocks.
if (End == LLVMBB->end()) {
HandlePHINodesInSuccessorBlocks(LLVMBB);
// Handle PHI nodes in successor blocks.
if (End == LLVMBB->end()) {
HandlePHINodesInSuccessorBlocks(LLVMBB);
// Lower the terminator after the copies are emitted.
SDL->visit(*LLVMBB->getTerminator());
// Lower the terminator after the copies are emitted.
SDL->visit(*LLVMBB->getTerminator());
}
}
// Make sure the root of the DAG is up-to-date.
CurDAG->setRoot(SDL->getControlRoot());
// Check whether calls in this block are real tail calls. Fix up CALL nodes
// with correct tailcall attribute so that the target can rely on the tailcall
// attribute indicating whether the call is really eligible for tail call
// optimization.
if (PerformTailCallOpt)
CheckDAGForTailCallsAndFixThem(*CurDAG, TLI);
// Final step, emit the lowered DAG as machine code.
CodeGenAndEmitDAG();
SDL->clear();

View File

@ -2584,45 +2584,3 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
DAG.getConstant(magics.s-1, getShiftAmountTy()));
}
}
/// IgnoreHarmlessInstructions - Ignore instructions between a CALL and RET
/// node that don't prevent tail call optimization.
static SDValue IgnoreHarmlessInstructions(SDValue node) {
// Found call return.
if (node.getOpcode() == ISD::CALL) return node;
// Ignore MERGE_VALUES. Will have at least one operand.
if (node.getOpcode() == ISD::MERGE_VALUES)
return IgnoreHarmlessInstructions(node.getOperand(0));
// Ignore ANY_EXTEND node.
if (node.getOpcode() == ISD::ANY_EXTEND)
return IgnoreHarmlessInstructions(node.getOperand(0));
if (node.getOpcode() == ISD::TRUNCATE)
return IgnoreHarmlessInstructions(node.getOperand(0));
// Any other node type.
return node;
}
bool TargetLowering::CheckTailCallReturnConstraints(CallSDNode *TheCall,
SDValue Ret) {
unsigned NumOps = Ret.getNumOperands();
// ISD::CALL results:(value0, ..., valuen, chain)
// ISD::RET operands:(chain, value0, flag0, ..., valuen, flagn)
// Value return:
// Check that operand of the RET node sources from the CALL node. The RET node
// has at least two operands. Operand 0 holds the chain. Operand 1 holds the
// value.
// Also we need to check that there is no code in between the call and the
// return. Hence we also check that the incomming chain to the return sources
// from the outgoing chain of the call.
if (NumOps > 1 &&
IgnoreHarmlessInstructions(Ret.getOperand(1)) == SDValue(TheCall,0) &&
Ret.getOperand(0) == SDValue(TheCall, TheCall->getNumValues()-1))
return true;
// void return: The RET node has the chain result value of the CALL node as
// input.
if (NumOps == 1 &&
Ret.getOperand(0) == SDValue(TheCall, TheCall->getNumValues()-1))
return true;
return false;
}

View File

@ -295,7 +295,6 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
setOperationAction(ISD::RET, MVT::Other, Custom);
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom);
@ -531,13 +530,6 @@ static bool FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode,
//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//
// The lower operations present on calling convention works on this order:
// LowerCALL (virt regs --> phys regs, virt regs --> stack)
// LowerFORMAL_ARGUMENTS (phys --> virt regs, stack --> virt regs)
// LowerRET (virt regs --> phys regs)
// LowerCALL (phys regs --> virt regs)
//
//===----------------------------------------------------------------------===//
#include "ARMGenCallingConv.inc"
@ -694,25 +686,21 @@ CCAssignFn *ARMTargetLowering::CCAssignFnForNode(unsigned CC,
}
}
/// LowerCallResult - Lower the result values of an ISD::CALL into the
/// appropriate copies out of appropriate physical registers. This assumes that
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
/// being lowered. The returns a SDNode with the same number of values as the
/// ISD::CALL.
SDNode *ARMTargetLowering::
LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG) {
/// LowerCallResult - Lower the result values of a call into the
/// appropriate copies out of appropriate physical registers.
SDValue
ARMTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
DebugLoc dl = TheCall->getDebugLoc();
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
bool isVarArg = TheCall->isVarArg();
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(),
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCInfo.AnalyzeCallResult(TheCall,
CCAssignFnForNode(CallingConv, /* Return*/ true));
SmallVector<SDValue, 8> ResultVals;
CCInfo.AnalyzeCallResult(Ins,
CCAssignFnForNode(CallConv, /* Return*/ true));
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@ -764,13 +752,10 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
break;
}
ResultVals.push_back(Val);
InVals.push_back(Val);
}
// Merge everything together with a MERGE_VALUES node.
ResultVals.push_back(Chain);
return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
&ResultVals[0], ResultVals.size()).getNode();
return Chain;
}
/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
@ -790,11 +775,11 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
/// LowerMemOpCallTo - Store the argument to the stack.
SDValue
ARMTargetLowering::LowerMemOpCallTo(CallSDNode *TheCall, SelectionDAG &DAG,
const SDValue &StackPtr,
const CCValAssign &VA, SDValue Chain,
SDValue Arg, ISD::ArgFlagsTy Flags) {
DebugLoc dl = TheCall->getDebugLoc();
ARMTargetLowering::LowerMemOpCallTo(SDValue Chain,
SDValue StackPtr, SDValue Arg,
DebugLoc dl, SelectionDAG &DAG,
const CCValAssign &VA,
ISD::ArgFlagsTy Flags) {
unsigned LocMemOffset = VA.getLocMemOffset();
SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset);
PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff);
@ -805,14 +790,13 @@ ARMTargetLowering::LowerMemOpCallTo(CallSDNode *TheCall, SelectionDAG &DAG,
PseudoSourceValue::getStack(), LocMemOffset);
}
void ARMTargetLowering::PassF64ArgInRegs(CallSDNode *TheCall, SelectionDAG &DAG,
void ARMTargetLowering::PassF64ArgInRegs(DebugLoc dl, SelectionDAG &DAG,
SDValue Chain, SDValue &Arg,
RegsToPassVector &RegsToPass,
CCValAssign &VA, CCValAssign &NextVA,
SDValue &StackPtr,
SmallVector<SDValue, 8> &MemOpChains,
ISD::ArgFlagsTy Flags) {
DebugLoc dl = TheCall->getDebugLoc();
SDValue fmrrd = DAG.getNode(ARMISD::FMRRD, dl,
DAG.getVTList(MVT::i32, MVT::i32), Arg);
@ -825,27 +809,30 @@ void ARMTargetLowering::PassF64ArgInRegs(CallSDNode *TheCall, SelectionDAG &DAG,
if (StackPtr.getNode() == 0)
StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy());
MemOpChains.push_back(LowerMemOpCallTo(TheCall, DAG, StackPtr, NextVA,
Chain, fmrrd.getValue(1), Flags));
MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, fmrrd.getValue(1),
dl, DAG, NextVA,
Flags));
}
}
/// LowerCALL - Lowering a ISD::CALL node into a callseq_start <-
/// LowerCall - Lowering a call into a callseq_start <-
/// ARMISD:CALL <- callseq_end chain. Also add input and output parameter
/// nodes.
SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
MVT RetVT = TheCall->getRetValType(0);
SDValue Chain = TheCall->getChain();
unsigned CC = TheCall->getCallingConv();
bool isVarArg = TheCall->isVarArg();
SDValue Callee = TheCall->getCallee();
DebugLoc dl = TheCall->getDebugLoc();
SDValue
ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeCallOperands(TheCall, CCAssignFnForNode(CC, /* Return*/ false));
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
*DAG.getContext());
CCInfo.AnalyzeCallOperands(Outs,
CCAssignFnForNode(CallConv, /* Return*/ false));
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@ -865,8 +852,8 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
i != e;
++i, ++realArgIdx) {
CCValAssign &VA = ArgLocs[i];
SDValue Arg = TheCall->getArg(realArgIdx);
ISD::ArgFlagsTy Flags = TheCall->getArgFlags(realArgIdx);
SDValue Arg = Outs[realArgIdx].Val;
ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags;
// Promote the value if needed.
switch (VA.getLocInfo()) {
@ -894,23 +881,23 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
SDValue Op1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg,
DAG.getConstant(1, MVT::i32));
PassF64ArgInRegs(TheCall, DAG, Chain, Op0, RegsToPass,
PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass,
VA, ArgLocs[++i], StackPtr, MemOpChains, Flags);
VA = ArgLocs[++i]; // skip ahead to next loc
if (VA.isRegLoc()) {
PassF64ArgInRegs(TheCall, DAG, Chain, Op1, RegsToPass,
PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass,
VA, ArgLocs[++i], StackPtr, MemOpChains, Flags);
} else {
assert(VA.isMemLoc());
if (StackPtr.getNode() == 0)
StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy());
MemOpChains.push_back(LowerMemOpCallTo(TheCall, DAG, StackPtr, VA,
Chain, Op1, Flags));
MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Op1,
dl, DAG, VA, Flags));
}
} else {
PassF64ArgInRegs(TheCall, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
StackPtr, MemOpChains, Flags);
}
} else if (VA.isRegLoc()) {
@ -920,8 +907,8 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
if (StackPtr.getNode() == 0)
StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy());
MemOpChains.push_back(LowerMemOpCallTo(TheCall, DAG, StackPtr, VA,
Chain, Arg, Flags));
MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg,
dl, DAG, VA, Flags));
}
}
@ -1024,30 +1011,30 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
DAG.getIntPtrConstant(0, true), InFlag);
if (RetVT != MVT::Other)
if (!Ins.empty())
InFlag = Chain.getValue(1);
// Handle result values, copying them out of physregs into vregs that we
// return.
return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG),
Op.getResNo());
return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins,
dl, DAG, InVals);
}
SDValue ARMTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
// The chain is always operand #0
SDValue Chain = Op.getOperand(0);
DebugLoc dl = Op.getDebugLoc();
SDValue
ARMTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
// CCValAssign - represent the assignment of the return value to a location.
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
// CCState - Info about the registers and stack slots.
CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs,
*DAG.getContext());
// Analyze return values of ISD::RET.
CCInfo.AnalyzeReturn(Op.getNode(), CCAssignFnForNode(CC, /* Return */ true));
// Analyze outgoing return values.
CCInfo.AnalyzeReturn(Outs, CCAssignFnForNode(CallConv, /* Return */ true));
// If this is the first return lowered for this function, add
// the regs to the liveout set for the function.
@ -1066,9 +1053,7 @@ SDValue ARMTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
// ISD::RET => ret chain, (regnum1,val1), ...
// So i*2+1 index only the regnums
SDValue Arg = Op.getOperand(realRVLocIdx*2+1);
SDValue Arg = Outs[realRVLocIdx].Val;
switch (VA.getLocInfo()) {
default: llvm_unreachable("Unknown loc info!");
@ -1172,7 +1157,7 @@ ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
// FIXME: is there useful debug info available here?
std::pair<SDValue, SDValue> CallResult =
LowerCallTo(Chain, (const Type *) Type::Int32Ty, false, false, false, false,
0, CallingConv::C, false,
0, CallingConv::C, false, /*isReturnValueUsed=*/true,
DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, dl);
return CallResult.first;
}
@ -1420,21 +1405,24 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA,
}
SDValue
ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
ARMTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
SDValue Root = Op.getOperand(0);
DebugLoc dl = Op.getDebugLoc();
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
unsigned CC = MF.getFunction()->getCallingConv();
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Op.getNode(),
CCAssignFnForNode(CC, /* Return*/ false));
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
*DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins,
CCAssignFnForNode(CallConv, /* Return*/ false));
SmallVector<SDValue, 16> ArgValues;
@ -1453,17 +1441,17 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
if (VA.getLocVT() == MVT::v2f64) {
SDValue ArgValue1 = GetF64FormalArgument(VA, ArgLocs[++i],
Root, DAG, dl);
Chain, DAG, dl);
VA = ArgLocs[++i]; // skip ahead to next loc
SDValue ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i],
Root, DAG, dl);
Chain, DAG, dl);
ArgValue = DAG.getNode(ISD::UNDEF, dl, MVT::v2f64);
ArgValue = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64,
ArgValue, ArgValue1, DAG.getIntPtrConstant(0));
ArgValue = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64,
ArgValue, ArgValue2, DAG.getIntPtrConstant(1));
} else
ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Root, DAG, dl);
ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
} else {
TargetRegisterClass *RC;
@ -1478,11 +1466,11 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
assert((RegVT == MVT::i32 || RegVT == MVT::f32 ||
(FloatABIType == FloatABI::Hard && RegVT == MVT::f64)) &&
"RegVT not supported by FORMAL_ARGUMENTS Lowering");
"RegVT not supported by formal arguments Lowering");
// Transform the arguments in physical registers into virtual ones.
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
ArgValue = DAG.getCopyFromReg(Root, dl, Reg, RegVT);
ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
}
// If this is an 8 or 16-bit value, it is really passed promoted
@ -1506,7 +1494,7 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
break;
}
ArgValues.push_back(ArgValue);
InVals.push_back(ArgValue);
} else { // VA.isRegLoc()
@ -1519,7 +1507,7 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
// Create load nodes to retrieve arguments from the stack.
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
ArgValues.push_back(DAG.getLoad(VA.getValVT(), dl, Root, FIN, NULL, 0));
InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0));
}
}
@ -1555,25 +1543,21 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
RC = ARM::GPRRegisterClass;
unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0);
MemOps.push_back(Store);
FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN,
DAG.getConstant(4, getPointerTy()));
}
if (!MemOps.empty())
Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOps[0], MemOps.size());
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOps[0], MemOps.size());
} else
// This will point to the next argument passed via stack.
VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset);
}
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
/// isFloatingPointZero - Return true if this is +0.0.
@ -2380,8 +2364,6 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) :
LowerGlobalAddressELF(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, Subtarget);
case ISD::BR_CC: return LowerBR_CC(Op, DAG, Subtarget);
case ISD::BR_JT: return LowerBR_JT(Op, DAG);
@ -2391,7 +2373,6 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT: return LowerFP_TO_INT(Op, DAG);
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::RETURNADDR: break;
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);

View File

@ -225,7 +225,7 @@ namespace llvm {
void addQRTypeForNEON(MVT VT);
typedef SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPassVector;
void PassF64ArgInRegs(CallSDNode *TheCall, SelectionDAG &DAG,
void PassF64ArgInRegs(DebugLoc dl, SelectionDAG &DAG,
SDValue Chain, SDValue &Arg,
RegsToPassVector &RegsToPass,
CCValAssign &VA, CCValAssign &NextVA,
@ -236,15 +236,12 @@ namespace llvm {
SDValue &Root, SelectionDAG &DAG, DebugLoc dl);
CCAssignFn *CCAssignFnForNode(unsigned CC, bool Return) const;
SDValue LowerMemOpCallTo(CallSDNode *TheCall, SelectionDAG &DAG,
const SDValue &StackPtr, const CCValAssign &VA,
SDValue Chain, SDValue Arg, ISD::ArgFlagsTy Flags);
SDNode *LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, SDValue Arg,
DebugLoc dl, SelectionDAG &DAG,
const CCValAssign &VA,
ISD::ArgFlagsTy Flags);
SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG);
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddressDarwin(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddressELF(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
@ -253,7 +250,6 @@ namespace llvm {
SDValue LowerToTLSExecModels(GlobalAddressSDNode *GA,
SelectionDAG &DAG);
SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG);
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG);
@ -264,6 +260,33 @@ namespace llvm {
bool AlwaysInline,
const Value *DstSV, uint64_t DstSVOff,
const Value *SrcSV, uint64_t SrcSVOff);
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
};
}

View File

@ -166,8 +166,6 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM)
setOperationAction(ISD::VAARG, MVT::Other, Custom);
setOperationAction(ISD::VAARG, MVT::i32, Custom);
setOperationAction(ISD::RET, MVT::Other, Custom);
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
@ -246,20 +244,21 @@ static SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) {
#include "AlphaGenCallingConv.inc"
SDValue AlphaTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = Op.getDebugLoc();
MachineFunction &MF = DAG.getMachineFunction();
unsigned CC = MF.getFunction()->getCallingConv();
SDValue
AlphaTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeCallOperands(TheCall, CC_Alpha);
CCInfo.AnalyzeCallOperands(Outs, CC_Alpha);
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@ -275,8 +274,7 @@ SDValue AlphaTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
// Arguments start after the 5 first operands of ISD::CALL
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
// Promote the value if needed.
switch (VA.getLocInfo()) {
@ -355,30 +353,26 @@ SDValue AlphaTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Handle result values, copying them out of physregs into vregs that we
// return.
return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG),
Op.getResNo());
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
Ins, dl, DAG, InVals);
}
/// LowerCallResult - Lower the result values of an ISD::CALL into the
/// appropriate copies out of appropriate physical registers. This assumes that
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
/// being lowered. Returns a SDNode with the same number of values as the
/// ISD::CALL.
SDNode*
/// LowerCallResult - Lower the result values of a call into the
/// appropriate copies out of appropriate physical registers.
///
SDValue
AlphaTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
CallSDNode *TheCall,
unsigned CallingConv,
SelectionDAG &DAG) {
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = TheCall->getDebugLoc();
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(), RVLocs,
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs,
*DAG.getContext());
CCInfo.AnalyzeCallResult(TheCall, RetCC_Alpha);
SmallVector<SDValue, 8> ResultVals;
CCInfo.AnalyzeCallResult(Ins, RetCC_Alpha);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@ -402,33 +396,31 @@ AlphaTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
if (VA.getLocInfo() != CCValAssign::Full)
RetValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RetValue);
ResultVals.push_back(RetValue);
InVals.push_back(RetValue);
}
ResultVals.push_back(Chain);
// Merge everything together with a MERGE_VALUES node.
return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
&ResultVals[0], ResultVals.size()).getNode();
return Chain;
}
static SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG,
int &VarArgsBase,
int &VarArgsOffset) {
SDValue
AlphaTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
std::vector<SDValue> ArgValues;
SDValue Root = Op.getOperand(0);
DebugLoc dl = Op.getDebugLoc();
unsigned args_int[] = {
Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21};
unsigned args_float[] = {
Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21};
for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues()-1; ArgNo != e; ++ArgNo) {
for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
SDValue argt;
MVT ObjectVT = Op.getValue(ArgNo).getValueType();
MVT ObjectVT = Ins[ArgNo].VT;
SDValue ArgVal;
if (ArgNo < 6) {
@ -438,17 +430,17 @@ static SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG,
case MVT::f64:
args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo],
&Alpha::F8RCRegClass);
ArgVal = DAG.getCopyFromReg(Root, dl, args_float[ArgNo], ObjectVT);
ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT);
break;
case MVT::f32:
args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo],
&Alpha::F4RCRegClass);
ArgVal = DAG.getCopyFromReg(Root, dl, args_float[ArgNo], ObjectVT);
ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT);
break;
case MVT::i64:
args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo],
&Alpha::GPRCRegClass);
ArgVal = DAG.getCopyFromReg(Root, dl, args_int[ArgNo], MVT::i64);
ArgVal = DAG.getCopyFromReg(Chain, dl, args_int[ArgNo], MVT::i64);
break;
}
} else { //more args
@ -458,59 +450,58 @@ static SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG,
// Create the SelectionDAG nodes corresponding to a load
//from this parameter
SDValue FIN = DAG.getFrameIndex(FI, MVT::i64);
ArgVal = DAG.getLoad(ObjectVT, dl, Root, FIN, NULL, 0);
ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0);
}
ArgValues.push_back(ArgVal);
InVals.push_back(ArgVal);
}
// If the functions takes variable number of arguments, copy all regs to stack
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
if (isVarArg) {
VarArgsOffset = (Op.getNode()->getNumValues()-1) * 8;
VarArgsOffset = Ins.size() * 8;
std::vector<SDValue> LS;
for (int i = 0; i < 6; ++i) {
if (TargetRegisterInfo::isPhysicalRegister(args_int[i]))
args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass);
SDValue argt = DAG.getCopyFromReg(Root, dl, args_int[i], MVT::i64);
SDValue argt = DAG.getCopyFromReg(Chain, dl, args_int[i], MVT::i64);
int FI = MFI->CreateFixedObject(8, -8 * (6 - i));
if (i == 0) VarArgsBase = FI;
SDValue SDFI = DAG.getFrameIndex(FI, MVT::i64);
LS.push_back(DAG.getStore(Root, dl, argt, SDFI, NULL, 0));
LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0));
if (TargetRegisterInfo::isPhysicalRegister(args_float[i]))
args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass);
argt = DAG.getCopyFromReg(Root, dl, args_float[i], MVT::f64);
argt = DAG.getCopyFromReg(Chain, dl, args_float[i], MVT::f64);
FI = MFI->CreateFixedObject(8, - 8 * (12 - i));
SDFI = DAG.getFrameIndex(FI, MVT::i64);
LS.push_back(DAG.getStore(Root, dl, argt, SDFI, NULL, 0));
LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0));
}
//Set up a token factor with all the stack traffic
Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LS[0], LS.size());
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LS[0], LS.size());
}
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size());
return Chain;
}
static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
DebugLoc dl = Op.getDebugLoc();
SDValue Copy = DAG.getCopyToReg(Op.getOperand(0), dl, Alpha::R26,
DAG.getNode(AlphaISD::GlobalRetAddr,
DebugLoc::getUnknownLoc(),
MVT::i64),
SDValue());
switch (Op.getNumOperands()) {
SDValue
AlphaTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
SDValue Copy = DAG.getCopyToReg(Chain, dl, Alpha::R26,
DAG.getNode(AlphaISD::GlobalRetAddr,
DebugLoc::getUnknownLoc(),
MVT::i64),
SDValue());
switch (Outs.size()) {
default:
llvm_unreachable("Do not know how to return this many arguments!");
case 1:
case 0:
break;
//return SDValue(); // ret void is legal
case 3: {
MVT ArgVT = Op.getOperand(1).getValueType();
case 1: {
MVT ArgVT = Outs[0].Val.getValueType();
unsigned ArgReg;
if (ArgVT.isInteger())
ArgReg = Alpha::R0;
@ -519,13 +510,13 @@ static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
ArgReg = Alpha::F0;
}
Copy = DAG.getCopyToReg(Copy, dl, ArgReg,
Op.getOperand(1), Copy.getValue(1));
Outs[0].Val, Copy.getValue(1));
if (DAG.getMachineFunction().getRegInfo().liveout_empty())
DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg);
break;
}
case 5: {
MVT ArgVT = Op.getOperand(1).getValueType();
case 2: {
MVT ArgVT = Outs[0].Val.getValueType();
unsigned ArgReg1, ArgReg2;
if (ArgVT.isInteger()) {
ArgReg1 = Alpha::R0;
@ -536,13 +527,13 @@ static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
ArgReg2 = Alpha::F1;
}
Copy = DAG.getCopyToReg(Copy, dl, ArgReg1,
Op.getOperand(1), Copy.getValue(1));
Outs[0].Val, Copy.getValue(1));
if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(),
DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg1)
== DAG.getMachineFunction().getRegInfo().liveout_end())
DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg1);
Copy = DAG.getCopyToReg(Copy, dl, ArgReg2,
Op.getOperand(3), Copy.getValue(1));
Outs[1].Val, Copy.getValue(1));
if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(),
DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg2)
== DAG.getMachineFunction().getRegInfo().liveout_end())
@ -589,11 +580,6 @@ SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
DebugLoc dl = Op.getDebugLoc();
switch (Op.getOpcode()) {
default: llvm_unreachable("Wasn't expecting to be able to lower this!");
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG,
VarArgsBase,
VarArgsOffset);
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::RET: return LowerRET(Op,DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::INTRINSIC_WO_CHAIN: {

View File

@ -82,9 +82,11 @@ namespace llvm {
// Friendly names for dumps
const char *getTargetNodeName(unsigned Opcode) const;
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDNode *LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG);
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
ConstraintType getConstraintType(const std::string &Constraint) const;
@ -107,6 +109,26 @@ namespace llvm {
void LowerVAARG(SDNode *N, SDValue &Chain, SDValue &DataPtr,
SelectionDAG &DAG);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
};
}

View File

@ -123,9 +123,6 @@ BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM)
setOperationAction(ISD::VAEND, MVT::Other, Expand);
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
// RET must be custom lowered, to meet ABI requirements
setOperationAction(ISD::RET, MVT::Other, Custom);
}
const char *BlackfinTargetLowering::getTargetNodeName(unsigned Opcode) const {
@ -160,27 +157,23 @@ SDValue BlackfinTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) {
return DAG.getNode(BFISD::Wrapper, DL, MVT::i32, Op);
}
// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG, FLAG0, ..., FLAGn) - This node
// represents the formal arguments for a function. CC# is a Constant value
// indicating the calling convention of the function, and ISVARARG is a
// flag that indicates whether the function is varargs or not. This node
// has one result value for each incoming argument, plus one for the output
// chain.
SDValue BlackfinTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
SelectionDAG &DAG) {
DebugLoc dl = Op.getDebugLoc();
SDValue Root = Op.getOperand(0);
unsigned CC = Op.getConstantOperandVal(1);
bool isVarArg = Op.getConstantOperandVal(2);
SDValue
BlackfinTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AllocateStack(12, 4); // ABI requires 12 bytes stack space
CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_Blackfin);
CCInfo.AnalyzeFormalArguments(Ins, CC_Blackfin);
SmallVector<SDValue, 8> ArgValues;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
@ -193,7 +186,7 @@ SDValue BlackfinTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
unsigned Reg = MF.getRegInfo().createVirtualRegister(RC);
MF.getRegInfo().addLiveIn(VA.getLocReg(), Reg);
SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, RegVT);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it is really passed promoted to 32
// bits. Insert an assert[sz]ext to capture this, then truncate to the
@ -208,35 +201,34 @@ SDValue BlackfinTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
if (VA.getLocInfo() != CCValAssign::Full)
ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
ArgValues.push_back(ArgValue);
InVals.push_back(ArgValue);
} else {
assert(VA.isMemLoc() && "CCValAssign must be RegLoc or MemLoc");
unsigned ObjSize = VA.getLocVT().getStoreSizeInBits()/8;
int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset());
SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
ArgValues.push_back(DAG.getLoad(VA.getValVT(), dl, Root, FIN, NULL, 0));
InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0));
}
}
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
SDValue BlackfinTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
SDValue
BlackfinTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
// CCValAssign - represent the assignment of the return value to locations.
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
DebugLoc dl = Op.getDebugLoc();
// CCState - Info about the registers and stack slot.
CCState CCInfo(CC, isVarArg, DAG.getTarget(), RVLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, DAG.getTarget(),
RVLocs, *DAG.getContext());
// Analize return values of ISD::RET
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_Blackfin);
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_Blackfin);
// If this is the first return lowered for this function, add the regs to the
// liveout set for the function.
@ -245,14 +237,13 @@ SDValue BlackfinTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
SDValue Chain = Op.getOperand(0);
SDValue Flag;
// Copy the result values into the output registers.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
SDValue Opi = Op.getOperand(i*2+1);
SDValue Opi = Outs[i].Val;
// Expand to i32 if necessary
switch (VA.getLocInfo()) {
@ -268,8 +259,6 @@ SDValue BlackfinTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
Opi = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Opi);
break;
}
// ISD::RET => ret chain, (regnum1,val1), ...
// So i*2+1 index only the regnums.
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Opi, SDValue());
// Guarantee that all emitted copies are stuck together with flags.
Flag = Chain.getValue(1);
@ -282,20 +271,21 @@ SDValue BlackfinTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
}
}
SDValue BlackfinTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
unsigned CallingConv = TheCall->getCallingConv();
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = TheCall->getDebugLoc();
SDValue
BlackfinTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallingConv, isVarArg, DAG.getTarget(), ArgLocs,
CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), ArgLocs,
*DAG.getContext());
CCInfo.AllocateStack(12, 4); // ABI requires 12 bytes stack space
CCInfo.AnalyzeCallOperands(TheCall, CC_Blackfin);
CCInfo.AnalyzeCallOperands(Outs, CC_Blackfin);
// Get the size of the outgoing arguments stack space requirement.
unsigned ArgsSize = CCInfo.getNextStackOffset();
@ -307,9 +297,7 @@ SDValue BlackfinTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
// Arguments start after the 5 first operands of ISD::CALL
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
// Promote the value if needed.
switch (VA.getLocInfo()) {
@ -383,11 +371,10 @@ SDValue BlackfinTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
CCState RVInfo(CallingConv, isVarArg, DAG.getTarget(), RVLocs,
CCState RVInfo(CallConv, isVarArg, DAG.getTarget(), RVLocs,
*DAG.getContext());
RVInfo.AnalyzeCallResult(TheCall, RetCC_Blackfin);
SmallVector<SDValue, 8> ResultVals;
RVInfo.AnalyzeCallResult(Ins, RetCC_Blackfin);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@ -417,16 +404,10 @@ SDValue BlackfinTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Truncate to valtype
if (RV.getLocInfo() != CCValAssign::Full)
Val = DAG.getNode(ISD::TRUNCATE, dl, RV.getValVT(), Val);
ResultVals.push_back(Val);
InVals.push_back(Val);
}
ResultVals.push_back(Chain);
// Merge everything together with a MERGE_VALUES node.
SDValue merge = DAG.getNode(ISD::MERGE_VALUES, dl,
TheCall->getVTList(), &ResultVals[0],
ResultVals.size());
return merge;
return Chain;
}
// Expansion of ADDE / SUBE. This is a bit involved since blackfin doesn't have
@ -477,9 +458,6 @@ SDValue BlackfinTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
// Frame & Return address. Currently unimplemented
case ISD::FRAMEADDR: return SDValue();
case ISD::RETURNADDR: return SDValue();
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
case ISD::ADDE:
case ISD::SUBE: return LowerADDE(Op, DAG);
}

View File

@ -51,10 +51,27 @@ namespace llvm {
private:
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerADDE(SDValue Op, SelectionDAG &DAG);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
};
} // end namespace llvm

View File

@ -115,7 +115,9 @@ namespace {
const Type *RetTy = Op.getNode()->getValueType(0).getTypeForMVT();
std::pair<SDValue, SDValue> CallInfo =
TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
0, CallingConv::C, false, Callee, Args, DAG,
0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
Callee, Args, DAG,
Op.getDebugLoc());
return CallInfo.first;
@ -396,9 +398,6 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
setOperationAction(ISD::JumpTable, VT, Custom);
}
// RET must be custom lowered, to meet ABI requirements
setOperationAction(ISD::RET, MVT::Other, Custom);
// VASTART needs to be custom lowered to use the VarArgsFrameIndex
setOperationAction(ISD::VASTART , MVT::Other, Custom);
@ -1008,16 +1007,17 @@ LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
return SDValue();
}
static SDValue
LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
{
SDValue
SPUTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SmallVector<SDValue, 48> ArgValues;
SDValue Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
DebugLoc dl = Op.getDebugLoc();
const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
@ -1029,9 +1029,8 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
// Add DAG nodes to load the arguments or copy them out of registers.
for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
ArgNo != e; ++ArgNo) {
MVT ObjectVT = Op.getValue(ArgNo).getValueType();
for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
MVT ObjectVT = Ins[ArgNo].VT;
unsigned ObjSize = ObjectVT.getSizeInBits()/8;
SDValue ArgVal;
@ -1042,7 +1041,7 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
default: {
std::string msg;
raw_string_ostream Msg(msg);
Msg << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
Msg << "LowerFormalArguments Unhandled argument type: "
<< ObjectVT.getMVTString();
llvm_report_error(Msg.str());
}
@ -1079,7 +1078,7 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
ArgVal = DAG.getCopyFromReg(Root, dl, VReg, ObjectVT);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
++ArgRegIdx;
} else {
// We need to load the argument to a virtual register if we determined
@ -1087,13 +1086,13 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
// or we're forced to do vararg
int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
ArgVal = DAG.getLoad(ObjectVT, dl, Root, FIN, NULL, 0);
ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0);
ArgOffset += StackSlotSize;
}
ArgValues.push_back(ArgVal);
InVals.push_back(ArgVal);
// Update the chain
Root = ArgVal.getOperand(0);
Chain = ArgVal.getOperand(0);
}
// vararg handling:
@ -1108,23 +1107,19 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
SDValue Store = DAG.getStore(Root, dl, ArgVal, FIN, NULL, 0);
Root = Store.getOperand(0);
SDValue Store = DAG.getStore(Chain, dl, ArgVal, FIN, NULL, 0);
Chain = Store.getOperand(0);
MemOps.push_back(Store);
// Increment address by stack slot size for the next stored argument
ArgOffset += StackSlotSize;
}
if (!MemOps.empty())
Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOps[0], MemOps.size());
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOps[0], MemOps.size());
}
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size());
return Chain;
}
/// isLSAAddress - Return the immediate to use if the specified
@ -1141,16 +1136,20 @@ static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
}
static SDValue
LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
unsigned NumOps = TheCall->getNumArgs();
SDValue
SPUTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
unsigned NumOps = Outs.size();
unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
DebugLoc dl = TheCall->getDebugLoc();
// Handy pointer type
MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
@ -1176,7 +1175,7 @@ LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
SmallVector<SDValue, 8> MemOpChains;
for (unsigned i = 0; i != NumOps; ++i) {
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
// PtrOff will be used to store the current argument to the stack if a
// register cannot be found for it.
@ -1308,50 +1307,46 @@ LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
DAG.getIntPtrConstant(0, true), InFlag);
if (TheCall->getValueType(0) != MVT::Other)
if (!Ins.empty())
InFlag = Chain.getValue(1);
SDValue ResultVals[3];
unsigned NumResults = 0;
// If the function returns void, just return the chain.
if (Ins.empty())
return Chain;
// If the call has results, copy the values out of the ret val registers.
switch (TheCall->getValueType(0).getSimpleVT()) {
switch (Ins[0].VT.getSimpleVT()) {
default: llvm_unreachable("Unexpected ret value!");
case MVT::Other: break;
case MVT::i32:
if (TheCall->getValueType(1) == MVT::i32) {
if (Ins.size() > 1 && Ins[1].VT == MVT::i32) {
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R4,
MVT::i32, InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
InVals.push_back(Chain.getValue(0));
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i32,
Chain.getValue(2)).getValue(1);
ResultVals[1] = Chain.getValue(0);
NumResults = 2;
InVals.push_back(Chain.getValue(0));
} else {
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i32,
InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
NumResults = 1;
InVals.push_back(Chain.getValue(0));
}
break;
case MVT::i64:
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i64,
InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
NumResults = 1;
InVals.push_back(Chain.getValue(0));
break;
case MVT::i128:
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i128,
InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
NumResults = 1;
InVals.push_back(Chain.getValue(0));
break;
case MVT::f32:
case MVT::f64:
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, TheCall->getValueType(0),
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, Ins[0].VT,
InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
NumResults = 1;
InVals.push_back(Chain.getValue(0));
break;
case MVT::v2f64:
case MVT::v2i64:
@ -1359,31 +1354,25 @@ LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
case MVT::v4i32:
case MVT::v8i16:
case MVT::v16i8:
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, TheCall->getValueType(0),
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, Ins[0].VT,
InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
NumResults = 1;
InVals.push_back(Chain.getValue(0));
break;
}
// If the function returns void, just return the chain.
if (NumResults == 0)
return Chain;
// Otherwise, merge everything together with a MERGE_VALUES node.
ResultVals[NumResults++] = Chain;
SDValue Res = DAG.getMergeValues(ResultVals, NumResults, dl);
return Res.getValue(Op.getResNo());
return Chain;
}
static SDValue
LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
SDValue
SPUTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
DebugLoc dl = Op.getDebugLoc();
CCState CCInfo(CC, isVarArg, TM, RVLocs, *DAG.getContext());
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCInfo.AnalyzeReturn(Outs, RetCC_SPU);
// If this is the first return lowered for this function, add the regs to the
// liveout set for the function.
@ -1392,7 +1381,6 @@ LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
SDValue Chain = Op.getOperand(0);
SDValue Flag;
// Copy the result values into the output registers.
@ -1400,7 +1388,7 @@ LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Op.getOperand(i*2+1), Flag);
Outs[i].Val, Flag);
Flag = Chain.getValue(1);
}
@ -2648,12 +2636,6 @@ SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
case ISD::ConstantFP:
return LowerConstantFP(Op, DAG);
case ISD::FORMAL_ARGUMENTS:
return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
case ISD::CALL:
return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
case ISD::RET:
return LowerRET(Op, DAG, getTargetMachine());
// i8, i64 math ops:
case ISD::ADD:

View File

@ -150,6 +150,28 @@ namespace llvm {
/// getFunctionAlignment - Return the Log2 alignment of this function.
virtual unsigned getFunctionAlignment(const Function *F) const;
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
};
}

View File

@ -4430,13 +4430,6 @@ def : Pat<(v4i32 v4i32Imm:$imm),
def : Pat<(i8 imm:$imm),
(ILHr8 imm:$imm)>;
//===----------------------------------------------------------------------===//
// Call instruction patterns:
//===----------------------------------------------------------------------===//
// Return void
def : Pat<(ret),
(RET)>;
//===----------------------------------------------------------------------===//
// Zero/Any/Sign extensions
//===----------------------------------------------------------------------===//

View File

@ -80,7 +80,6 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
setOperationAction(ISD::ROTR, MVT::i8, Expand);
setOperationAction(ISD::ROTL, MVT::i16, Expand);
setOperationAction(ISD::ROTR, MVT::i16, Expand);
setOperationAction(ISD::RET, MVT::Other, Custom);
setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
@ -129,12 +128,9 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) {
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::SHL: // FALLTHROUGH
case ISD::SRL:
case ISD::SRA: return LowerShifts(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG);
case ISD::BR_CC: return LowerBR_CC(Op, DAG);
@ -157,27 +153,41 @@ unsigned MSP430TargetLowering::getFunctionAlignment(const Function *F) const {
#include "MSP430GenCallingConv.inc"
SDValue MSP430TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
SelectionDAG &DAG) {
unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
switch (CC) {
SDValue
MSP430TargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
switch (CallConv) {
default:
llvm_unreachable("Unsupported calling convention");
case CallingConv::C:
case CallingConv::Fast:
return LowerCCCArguments(Op, DAG);
return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals);
}
}
SDValue MSP430TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
unsigned CallingConv = TheCall->getCallingConv();
switch (CallingConv) {
SDValue
MSP430TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
switch (CallConv) {
default:
llvm_unreachable("Unsupported calling convention");
case CallingConv::Fast:
case CallingConv::C:
return LowerCCCCallTo(Op, DAG, CallingConv);
return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
Outs, Ins, dl, DAG, InVals);
}
}
@ -185,24 +195,27 @@ SDValue MSP430TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
/// generate load operations for arguments places on the stack.
// FIXME: struct return stuff
// FIXME: varargs
SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Op,
SelectionDAG &DAG) {
SDValue
MSP430TargetLowering::LowerCCCArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SDValue Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
unsigned CC = MF.getFunction()->getCallingConv();
DebugLoc dl = Op.getDebugLoc();
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_MSP430);
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CC_MSP430);
assert(!isVarArg && "Varargs not supported yet");
SmallVector<SDValue, 16> ArgValues;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
if (VA.isRegLoc()) {
@ -212,7 +225,7 @@ SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Op,
default:
{
#ifndef NDEBUG
cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
cerr << "LowerFormalArguments Unhandled argument type: "
<< RegVT.getSimpleVT() << "\n";
#endif
llvm_unreachable(0);
@ -221,7 +234,7 @@ SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Op,
unsigned VReg =
RegInfo.createVirtualRegister(MSP430::GR16RegisterClass);
RegInfo.addLiveIn(VA.getLocReg(), VReg);
SDValue ArgValue = DAG.getCopyFromReg(Root, dl, VReg, RegVT);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
// If this is an 8-bit value, it is really passed promoted to 16
// bits. Insert an assert[sz]ext to capture this, then truncate to the
@ -236,7 +249,7 @@ SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Op,
if (VA.getLocInfo() != CCValAssign::Full)
ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
ArgValues.push_back(ArgValue);
InVals.push_back(ArgValue);
}
} else {
// Sanity check
@ -244,7 +257,7 @@ SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Op,
// Load the argument to a virtual register
unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
if (ObjSize > 2) {
cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
cerr << "LowerFormalArguments Unhandled argument type: "
<< VA.getLocVT().getSimpleVT()
<< "\n";
}
@ -254,30 +267,29 @@ SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Op,
// Create the SelectionDAG nodes corresponding to a load
//from this parameter
SDValue FIN = DAG.getFrameIndex(FI, MVT::i16);
ArgValues.push_back(DAG.getLoad(VA.getLocVT(), dl, Root, FIN,
PseudoSourceValue::getFixedStack(FI), 0));
InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
PseudoSourceValue::getFixedStack(FI), 0));
}
}
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
SDValue MSP430TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
SDValue
MSP430TargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
// CCValAssign - represent the assignment of the return value to a location
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
DebugLoc dl = Op.getDebugLoc();
// CCState - Info about the registers and stack slot.
CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
// Analize return values of ISD::RET
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_MSP430);
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_MSP430);
// If this is the first return lowered for this function, add the regs to the
// liveout set for the function.
@ -287,8 +299,6 @@ SDValue MSP430TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
// The chain is always operand #0
SDValue Chain = Op.getOperand(0);
SDValue Flag;
// Copy the result values into the output registers.
@ -296,10 +306,8 @@ SDValue MSP430TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
// ISD::RET => ret chain, (regnum1,val1), ...
// So i*2+1 index only the regnums
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Op.getOperand(i*2+1), Flag);
Outs[i].Val, Flag);
// Guarantee that all emitted copies are stuck together,
// avoiding something bad.
@ -316,19 +324,21 @@ SDValue MSP430TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
/// LowerCCCCallTo - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
/// TODO: sret.
SDValue MSP430TargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
unsigned CC) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = Op.getDebugLoc();
SDValue
MSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg>
&Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeCallOperands(TheCall, CC_MSP430);
CCInfo.AnalyzeCallOperands(Outs, CC_MSP430);
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@ -344,8 +354,7 @@ SDValue MSP430TargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
// Arguments start after the 5 first operands of ISD::CALL
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
// Promote the value if needed.
switch (VA.getLocInfo()) {
@ -434,44 +443,36 @@ SDValue MSP430TargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
// Handle result values, copying them out of physregs into vregs that we
// return.
return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG),
Op.getResNo());
return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl,
DAG, InVals);
}
/// LowerCallResult - Lower the result values of an ISD::CALL into the
/// appropriate copies out of appropriate physical registers. This assumes that
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
/// being lowered. Returns a SDNode with the same number of values as the
/// ISD::CALL.
SDNode*
/// LowerCallResult - Lower the result values of a call into the
/// appropriate copies out of appropriate physical registers.
///
SDValue
MSP430TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
CallSDNode *TheCall,
unsigned CallingConv,
SelectionDAG &DAG) {
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = TheCall->getDebugLoc();
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(),
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCInfo.AnalyzeCallResult(TheCall, RetCC_MSP430);
SmallVector<SDValue, 8> ResultVals;
CCInfo.AnalyzeCallResult(Ins, RetCC_MSP430);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
RVLocs[i].getValVT(), InFlag).getValue(1);
InFlag = Chain.getValue(2);
ResultVals.push_back(Chain.getValue(0));
InVals.push_back(Chain.getValue(0));
}
ResultVals.push_back(Chain);
// Merge everything together with a MERGE_VALUES node.
return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
&ResultVals[0], ResultVals.size()).getNode();
return Chain;
}
SDValue MSP430TargetLowering::LowerShifts(SDValue Op,

View File

@ -33,7 +33,7 @@ namespace llvm {
/// Y = RRC X, rotate right via carry
RRC,
/// CALL/TAILCALL - These operations represent an abstract call
/// CALL - These operations represent an abstract call
/// instruction, which includes a bunch of information.
CALL,
@ -77,10 +77,6 @@ namespace llvm {
/// getFunctionAlignment - Return the Log2 alignment of this function.
virtual unsigned getFunctionAlignment(const Function *F) const;
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG);
SDValue LowerShifts(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG);
@ -88,16 +84,52 @@ namespace llvm {
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG);
SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
unsigned CC);
SDNode* LowerCallResult(SDValue Chain, SDValue InFlag,
CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG);
MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const;
private:
SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue LowerCCCArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
const MSP430Subtarget &Subtarget;
const MSP430TargetMachine &TM;
};

View File

@ -94,7 +94,6 @@ MipsTargetLowering(MipsTargetMachine &TM)
// Mips Custom Operations
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::RET, MVT::Other, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::SELECT, MVT::f32, Custom);
@ -182,16 +181,13 @@ LowerOperation(SDValue Op, SelectionDAG &DAG)
{
case ISD::AND: return LowerANDOR(Op, DAG);
case ISD::BRCOND: return LowerBRCOND(Op, DAG);
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::OR: return LowerANDOR(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
case ISD::SELECT: return LowerSELECT(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
}
@ -580,13 +576,6 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG)
//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//
// The lower operations present on calling convention works on this order:
// LowerCALL (virt regs --> phys regs, virt regs --> stack)
// LowerFORMAL_ARGUMENTS (phys --> virt regs, stack --> virt regs)
// LowerRET (virt regs --> phys regs)
// LowerCALL (phys regs --> virt regs)
//
//===----------------------------------------------------------------------===//
#include "MipsGenCallingConv.inc"
@ -671,38 +660,37 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT,
}
//===----------------------------------------------------------------------===//
// CALL Calling Convention Implementation
// Call Calling Convention Implementation
//===----------------------------------------------------------------------===//
/// LowerCALL - functions arguments are copied from virtual regs to
/// LowerCall - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
/// TODO: isVarArg, isTailCall.
SDValue MipsTargetLowering::
LowerCALL(SDValue Op, SelectionDAG &DAG)
{
SDValue
MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
bool isVarArg = TheCall->isVarArg();
unsigned CC = TheCall->getCallingConv();
DebugLoc dl = TheCall->getDebugLoc();
MachineFrameInfo *MFI = MF.getFrameInfo();
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
*DAG.getContext());
// To meet O32 ABI, Mips must always allocate 16 bytes on
// the stack (even if less than 4 are used as arguments)
if (Subtarget->isABI_O32()) {
int VTsize = MVT(MVT::i32).getSizeInBits()/8;
MFI->CreateFixedObject(VTsize, (VTsize*3));
CCInfo.AnalyzeCallOperands(TheCall, CC_MipsO32);
CCInfo.AnalyzeCallOperands(Outs, CC_MipsO32);
} else
CCInfo.AnalyzeCallOperands(TheCall, CC_Mips);
CCInfo.AnalyzeCallOperands(Outs, CC_Mips);
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@ -719,7 +707,7 @@ LowerCALL(SDValue Op, SelectionDAG &DAG)
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
CCValAssign &VA = ArgLocs[i];
// Promote the value if needed.
@ -859,76 +847,69 @@ LowerCALL(SDValue Op, SelectionDAG &DAG)
// Handle result values, copying them out of physregs into vregs that we
// return.
return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG), Op.getResNo());
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
Ins, dl, DAG, InVals);
}
/// LowerCallResult - Lower the result values of an ISD::CALL into the
/// appropriate copies out of appropriate physical registers. This assumes that
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
/// being lowered. Returns a SDNode with the same number of values as the
/// ISD::CALL.
SDNode *MipsTargetLowering::
LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG) {
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = TheCall->getDebugLoc();
/// LowerCallResult - Lower the result values of a call into the
/// appropriate copies out of appropriate physical registers.
SDValue
MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(),
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCInfo.AnalyzeCallResult(TheCall, RetCC_Mips);
SmallVector<SDValue, 8> ResultVals;
CCInfo.AnalyzeCallResult(Ins, RetCC_Mips);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
RVLocs[i].getValVT(), InFlag).getValue(1);
RVLocs[i].getValVT(), InFlag).getValue(1);
InFlag = Chain.getValue(2);
ResultVals.push_back(Chain.getValue(0));
InVals.push_back(Chain.getValue(0));
}
ResultVals.push_back(Chain);
// Merge everything together with a MERGE_VALUES node.
return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
&ResultVals[0], ResultVals.size()).getNode();
return Chain;
}
//===----------------------------------------------------------------------===//
// FORMAL_ARGUMENTS Calling Convention Implementation
// Formal Arguments Calling Convention Implementation
//===----------------------------------------------------------------------===//
/// LowerFORMAL_ARGUMENTS - transform physical registers into
/// LowerFormalArguments - transform physical registers into
/// virtual registers and generate load operations for
/// arguments places on the stack.
/// TODO: isVarArg
SDValue MipsTargetLowering::
LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
{
SDValue Root = Op.getOperand(0);
SDValue
MipsTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
DebugLoc dl = Op.getDebugLoc();
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF);
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
if (Subtarget->isABI_O32())
CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_MipsO32);
CCInfo.AnalyzeFormalArguments(Ins, CC_MipsO32);
else
CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_Mips);
CCInfo.AnalyzeFormalArguments(Ins, CC_Mips);
SmallVector<SDValue, 16> ArgValues;
SDValue StackPtr;
unsigned FirstStackArgLoc = (Subtarget->isABI_EABI() ? 0 : 16);
@ -949,12 +930,12 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
if (!Subtarget->isSingleFloat())
RC = Mips::AFGR64RegisterClass;
} else
llvm_unreachable("RegVT not supported by FORMAL_ARGUMENTS Lowering");
llvm_unreachable("RegVT not supported by LowerFormalArguments Lowering");
// Transform the arguments stored on
// physical registers into virtual ones
unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC);
SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, RegVT);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it has been passed promoted
// to 32 bits. Insert an assert[sz]ext to capture this, then
@ -978,14 +959,14 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
if (RegVT == MVT::i32 && VA.getValVT() == MVT::f64) {
unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(),
VA.getLocReg()+1, RC);
SDValue ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg2, RegVT);
SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT);
SDValue Hi = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, ArgValue);
SDValue Lo = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, ArgValue2);
ArgValue = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::f64, Lo, Hi);
}
}
ArgValues.push_back(ArgValue);
InVals.push_back(ArgValue);
// To meet ABI, when VARARGS are passed on registers, the registers
// must have their values written to the caller stack frame.
@ -1007,7 +988,7 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
// emit ISD::STORE whichs stores the
// parameter value to a stack Location
ArgValues.push_back(DAG.getStore(Root, dl, ArgValue, PtrOff, NULL, 0));
InVals.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0));
}
} else { // VA.isRegLoc()
@ -1030,7 +1011,7 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
// Create load nodes to retrieve arguments from the stack
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
ArgValues.push_back(DAG.getLoad(VA.getValVT(), dl, Root, FIN, NULL, 0));
InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0));
}
}
@ -1043,36 +1024,33 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i32));
MipsFI->setSRetReturnReg(Reg);
}
SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, ArgValues[0]);
Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Root);
SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]);
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
}
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
//===----------------------------------------------------------------------===//
// Return Value Calling Convention Implementation
//===----------------------------------------------------------------------===//
SDValue MipsTargetLowering::
LowerRET(SDValue Op, SelectionDAG &DAG)
{
SDValue
MipsTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
// CCValAssign - represent the assignment of
// the return value to a location
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
DebugLoc dl = Op.getDebugLoc();
// CCState - Info about the registers and stack slot.
CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
// Analize return values of ISD::RET
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_Mips);
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_Mips);
// If this is the first return lowered for this function, add
// the regs to the liveout set for the function.
@ -1082,8 +1060,6 @@ LowerRET(SDValue Op, SelectionDAG &DAG)
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
// The chain is always operand #0
SDValue Chain = Op.getOperand(0);
SDValue Flag;
// Copy the result values into the output registers.
@ -1091,10 +1067,8 @@ LowerRET(SDValue Op, SelectionDAG &DAG)
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
// ISD::RET => ret chain, (regnum1,val1), ...
// So i*2+1 index only the regnums
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Op.getOperand(i*2+1), Flag);
Outs[i].Val, Flag);
// guarantee that all emitted copies are
// stuck together, avoiding something bad

View File

@ -89,24 +89,46 @@ namespace llvm {
const MipsSubtarget *Subtarget;
// Lower Operand helpers
SDNode *LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG);
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
// Lower Operand specifics
SDValue LowerANDOR(SDValue Op, SelectionDAG &DAG);
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG);
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *MBB) const;

View File

@ -57,7 +57,7 @@ private:
/// to be used on emitPrologue and processFunctionBeforeFrameFinalized.
MipsFIHolder GPHolder;
/// On LowerFORMAL_ARGUMENTS the stack size is unknown, so the Stack
/// On LowerFormalArguments the stack size is unknown, so the Stack
/// Pointer Offset calculation of "not in register arguments" must be
/// postponed to emitPrologue.
SmallVector<MipsFIHolder, 16> FnLoadArgs;
@ -65,7 +65,7 @@ private:
// When VarArgs, we must write registers back to caller stack, preserving
// on register arguments. Since the stack size is unknown on
// LowerFORMAL_ARGUMENTS, the Stack Pointer Offset calculation must be
// LowerFormalArguments, the Stack Pointer Offset calculation must be
// postponed to emitPrologue.
SmallVector<MipsFIHolder, 4> FnStoreVarArgs;
bool HasStoreVarArgs;

View File

@ -212,7 +212,7 @@ getReservedRegs(const MachineFunction &MF) const
// The emitted instruction will be something like:
// lw REGX, 16+StackSize(SP)
//
// Since the total stack size is unknown on LowerFORMAL_ARGUMENTS, all
// Since the total stack size is unknown on LowerFormalArguments, all
// stack references (ObjectOffset) created to reference the function
// arguments, are negative numbers. This way, on eliminateFrameIndex it's
// possible to detect those references and the offsets are adjusted to
@ -234,7 +234,7 @@ void MipsRegisterInfo::adjustMipsStackFrame(MachineFunction &MF) const
int TopCPUSavedRegOff = -1, TopFPUSavedRegOff = -1;
// Replace the dummy '0' SPOffset by the negative offsets, as explained on
// LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid
// LowerFormalArguments. Leaving '0' for while is necessary to avoid
// the approach done by calculateFrameObjectOffsets to the stack frame.
MipsFI->adjustLoadArgsFI(MFI);
MipsFI->adjustStoreVarArgsFI(MFI);
@ -378,7 +378,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
DOUT << "stackSize : " << stackSize << "\n";
#endif
// as explained on LowerFORMAL_ARGUMENTS, detect negative offsets
// as explained on LowerFormalArguments, detect negative offsets
// and adjust SPOffsets considering the final stack size.
int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset));
Offset += MI.getOperand(i-1).getImm();

View File

@ -268,8 +268,6 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
setOperationAction(ISD::XOR, MVT::i8, Custom);
setOperationAction(ISD::FrameIndex, MVT::i16, Custom);
setOperationAction(ISD::CALL, MVT::i16, Custom);
setOperationAction(ISD::RET, MVT::Other, Custom);
setOperationAction(ISD::MUL, MVT::i8, Custom);
@ -410,7 +408,9 @@ PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call,
const Type *RetTy = RetVT.getTypeForMVT();
std::pair<SDValue,SDValue> CallInfo =
LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
false, 0, CallingConv::C, false, Callee, Args, DAG, dl);
false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
Callee, Args, DAG, dl);
return CallInfo.first;
}
@ -440,6 +440,7 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const {
case PIC16ISD::SUBCC: return "PIC16ISD::SUBCC";
case PIC16ISD::SELECT_ICC: return "PIC16ISD::SELECT_ICC";
case PIC16ISD::BRCOND: return "PIC16ISD::BRCOND";
case PIC16ISD::RET: return "PIC16ISD::RET";
case PIC16ISD::Dummy: return "PIC16ISD::Dummy";
}
}
@ -994,12 +995,8 @@ PIC16TargetLowering::LowerOperationWrapper(SDNode *N,
SDValue Res;
unsigned i;
switch (Op.getOpcode()) {
case ISD::FORMAL_ARGUMENTS:
Res = LowerFORMAL_ARGUMENTS(Op, DAG); break;
case ISD::LOAD:
Res = ExpandLoad(Op.getNode(), DAG); break;
case ISD::CALL:
Res = LowerCALL(Op, DAG); break;
default: {
// All other operations are handled in LowerOperation.
Res = LowerOperation(Op, DAG);
@ -1019,8 +1016,6 @@ PIC16TargetLowering::LowerOperationWrapper(SDNode *N,
SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) {
case ISD::FORMAL_ARGUMENTS:
return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::ADD:
case ISD::ADDC:
case ISD::ADDE:
@ -1043,10 +1038,6 @@ SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::AND:
case ISD::XOR:
return LowerBinOp(Op, DAG);
case ISD::CALL:
return LowerCALL(Op, DAG);
case ISD::RET:
return LowerRET(Op, DAG);
case ISD::BR_CC:
return LowerBR_CC(Op, DAG);
case ISD::SELECT_CC:
@ -1091,12 +1082,11 @@ SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op,
}
SDValue PIC16TargetLowering::
LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag,
LowerIndirectCallArguments(SDValue Chain, SDValue InFlag,
SDValue DataAddr_Lo, SDValue DataAddr_Hi,
SelectionDAG &DAG) {
CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
unsigned NumOps = TheCall->getNumArgs();
DebugLoc dl = TheCall->getDebugLoc();
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
unsigned NumOps = Outs.size();
// If call has no arguments then do nothing and return.
if (NumOps == 0)
@ -1107,10 +1097,10 @@ LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag,
SDValue Arg, StoreRet;
// For PIC16 ABI the arguments come after the return value.
unsigned RetVals = TheCall->getNumRetVals();
unsigned RetVals = Outs.size();
for (unsigned i = 0, ArgOffset = RetVals; i < NumOps; i++) {
// Get the arguments
Arg = TheCall->getArg(i);
Arg = Outs[i].Val;
Ops.clear();
Ops.push_back(Chain);
@ -1130,16 +1120,14 @@ LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag,
}
SDValue PIC16TargetLowering::
LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue ArgLabel,
SDValue InFlag, SelectionDAG &DAG) {
CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
unsigned NumOps = TheCall->getNumArgs();
DebugLoc dl = TheCall->getDebugLoc();
LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
unsigned NumOps = Outs.size();
std::string Name;
SDValue Arg, StoreAt;
MVT ArgVT;
unsigned Size=0;
unsigned ArgCount=0;
// If call has no arguments then do nothing and return.
if (NumOps == 0)
@ -1157,9 +1145,9 @@ LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue ArgLabel,
std::vector<SDValue> Ops;
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
for (unsigned i=ArgCount, Offset = 0; i<NumOps; i++) {
for (unsigned i=0, Offset = 0; i<NumOps; i++) {
// Get the argument
Arg = TheCall->getArg(i);
Arg = Outs[i].Val;
StoreOffset = (Offset + AddressOffset);
// Store the argument on frame
@ -1187,12 +1175,12 @@ LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue ArgLabel,
}
SDValue PIC16TargetLowering::
LowerIndirectCallReturn (SDValue Op, SDValue Chain, SDValue InFlag,
SDValue DataAddr_Lo, SDValue DataAddr_Hi,
SelectionDAG &DAG) {
CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
DebugLoc dl = TheCall->getDebugLoc();
unsigned RetVals = TheCall->getNumRetVals();
LowerIndirectCallReturn(SDValue Chain, SDValue InFlag,
SDValue DataAddr_Lo, SDValue DataAddr_Hi,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
unsigned RetVals = Ins.size();
// If call does not have anything to return
// then do nothing and go back.
@ -1200,7 +1188,6 @@ LowerIndirectCallReturn (SDValue Op, SDValue Chain, SDValue InFlag,
return Chain;
// Call has something to return
std::vector<SDValue> ResultVals;
SDValue LoadRet;
SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
@ -1210,23 +1197,20 @@ LowerIndirectCallReturn (SDValue Op, SDValue Chain, SDValue InFlag,
InFlag);
InFlag = getOutFlag(LoadRet);
Chain = getChain(LoadRet);
ResultVals.push_back(LoadRet);
InVals.push_back(LoadRet);
}
ResultVals.push_back(Chain);
SDValue Res = DAG.getMergeValues(&ResultVals[0], ResultVals.size(), dl);
return Res;
return Chain;
}
SDValue PIC16TargetLowering::
LowerDirectCallReturn(SDValue Op, SDValue Chain, SDValue RetLabel,
SDValue InFlag, SelectionDAG &DAG) {
CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
DebugLoc dl = TheCall->getDebugLoc();
LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Currently handling primitive types only. They will come in
// i8 parts
unsigned RetVals = TheCall->getNumRetVals();
std::vector<SDValue> ResultVals;
unsigned RetVals = Ins.size();
// Return immediately if the return type is void
if (RetVals == 0)
@ -1252,29 +1236,20 @@ LowerDirectCallReturn(SDValue Op, SDValue Chain, SDValue RetLabel,
Chain = getChain(LoadRet);
Offset++;
ResultVals.push_back(LoadRet);
InVals.push_back(LoadRet);
}
// To return use MERGE_VALUES
ResultVals.push_back(Chain);
SDValue Res = DAG.getMergeValues(&ResultVals[0], ResultVals.size(), dl);
return Res;
return Chain;
}
SDValue PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
SDValue Chain = Op.getOperand(0);
DebugLoc dl = Op.getDebugLoc();
SDValue
PIC16TargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
if (Op.getNumOperands() == 1) // return void
return Op;
// return should have odd number of operands
if ((Op.getNumOperands() % 2) == 0 ) {
llvm_unreachable("Do not know how to return this many arguments!");
}
// Number of values to return
unsigned NumRet = (Op.getNumOperands() / 2);
unsigned NumRet = Outs.size();
// Function returns value always on stack with the offset starting
// from 0
@ -1288,68 +1263,13 @@ SDValue PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
SDValue BS = DAG.getConstant(1, MVT::i8);
SDValue RetVal;
for(unsigned i=0;i<NumRet; ++i) {
RetVal = Op.getNode()->getOperand(2*i + 1);
RetVal = Outs[i].Val;
Chain = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, RetVal,
ES, BS,
DAG.getConstant (i, MVT::i8));
}
return DAG.getNode(ISD::RET, dl, MVT::Other, Chain);
}
// CALL node may have some operands non-legal to PIC16. Generate new CALL
// node with all the operands legal.
// Currently only Callee operand of the CALL node is non-legal. This function
// legalizes the Callee operand and uses all other operands as are to generate
// new CALL node.
SDValue PIC16TargetLowering::LegalizeCALL(SDValue Op, SelectionDAG &DAG) {
CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
DebugLoc dl = TheCall->getDebugLoc();
unsigned i =0;
assert(Callee.getValueType() == MVT::i16 &&
"Don't know how to legalize this call node!!!");
assert(Callee.getOpcode() == ISD::BUILD_PAIR &&
"Don't know how to legalize this call node!!!");
if (isDirectAddress(Callee)) {
// Come here for direct calls
Callee = Callee.getOperand(0).getOperand(0);
} else {
// Come here for indirect calls
SDValue Lo, Hi;
// Indirect addresses. Get the hi and lo parts of ptr.
GetExpandedParts(Callee, DAG, Lo, Hi);
// Connect Lo and Hi parts of the callee with the PIC16Connect
Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi);
}
std::vector<SDValue> Ops;
Ops.push_back(Chain);
Ops.push_back(Callee);
// Add the call arguments and their flags
unsigned NumArgs = TheCall->getNumArgs();
for(i=0;i<NumArgs;i++) {
Ops.push_back(TheCall->getArg(i));
Ops.push_back(TheCall->getArgFlagsVal(i));
}
std::vector<MVT> NodeTys;
unsigned NumRets = TheCall->getNumRetVals();
for(i=0;i<NumRets;i++)
NodeTys.push_back(TheCall->getRetValType(i));
// Return a Chain as well
NodeTys.push_back(MVT::Other);
SDVTList VTs = DAG.getVTList(&NodeTys[0], NodeTys.size());
// Generate new call with all the operands legal
return DAG.getCall(TheCall->getCallingConv(), dl,
TheCall->isVarArg(), TheCall->isTailCall(),
TheCall->isInreg(), VTs, &Ops[0], Ops.size(),
TheCall->getNumFixedArgs());
return DAG.getNode(PIC16ISD::RET, dl, MVT::Other, Chain);
}
void PIC16TargetLowering::
@ -1414,36 +1334,40 @@ GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain,
DataAddr_Hi = DAG.getNode(PIC16ISD::MTHI, dl, MVT::i8, Call, OperFlag);
}
SDValue
PIC16TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
DebugLoc dl = TheCall->getDebugLoc();
if (Callee.getValueType() == MVT::i16 &&
Callee.getOpcode() == ISD::BUILD_PAIR) {
// Control should come here only from TypeLegalizer for lowering
// Legalize the non-legal arguments of call and return the
// new call with legal arguments.
return LegalizeCALL(Op, DAG);
}
// Control should come here from Legalize DAG.
// Here all the operands of CALL node should be legal.
// If this is an indirect call then to pass the arguments
// and read the return value back, we need the data address
// of the function being called.
// To get the data address two more calls need to be made.
assert(Callee.getValueType() == MVT::i16 &&
"Don't know how to legalize this call node!!!");
// The flag to track if this is a direct or indirect call.
bool IsDirectCall = true;
unsigned RetVals = TheCall->getNumRetVals();
unsigned NumArgs = TheCall->getNumArgs();
unsigned RetVals = Ins.size();
unsigned NumArgs = Outs.size();
SDValue DataAddr_Lo, DataAddr_Hi;
if (Callee.getOpcode() == PIC16ISD::PIC16Connect) {
if (!isa<GlobalAddressSDNode>(Callee) &&
!isa<ExternalSymbolSDNode>(Callee)) {
IsDirectCall = false; // This is indirect call
// If this is an indirect call then to pass the arguments
// and read the return value back, we need the data address
// of the function being called.
// To get the data address two more calls need to be made.
// Come here for indirect calls
SDValue Lo, Hi;
// Indirect addresses. Get the hi and lo parts of ptr.
GetExpandedParts(Callee, DAG, Lo, Hi);
// Connect Lo and Hi parts of the callee with the PIC16Connect
Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi);
// Read DataAddress only if we have to pass arguments or
// read return value.
if ((RetVals > 0) || (NumArgs > 0))
@ -1499,12 +1423,13 @@ SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Pass the argument to function before making the call.
SDValue CallArgs;
if (IsDirectCall) {
CallArgs = LowerDirectCallArguments(Op, Chain, ArgLabel, OperFlag, DAG);
CallArgs = LowerDirectCallArguments(ArgLabel, Chain, OperFlag,
Outs, dl, DAG);
Chain = getChain(CallArgs);
OperFlag = getOutFlag(CallArgs);
} else {
CallArgs = LowerIndirectCallArguments(Op, Chain, OperFlag, DataAddr_Lo,
DataAddr_Hi, DAG);
CallArgs = LowerIndirectCallArguments(Chain, OperFlag, DataAddr_Lo,
DataAddr_Hi, Outs, dl, DAG);
Chain = getChain(CallArgs);
OperFlag = getOutFlag(CallArgs);
}
@ -1525,10 +1450,11 @@ SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Lower the return value reading after the call.
if (IsDirectCall)
return LowerDirectCallReturn(Op, Chain, RetLabel, OperFlag, DAG);
return LowerDirectCallReturn(RetLabel, Chain, OperFlag,
Ins, dl, DAG, InVals);
else
return LowerIndirectCallReturn(Op, Chain, OperFlag, DataAddr_Lo,
DataAddr_Hi, DAG);
return LowerIndirectCallReturn(Chain, OperFlag, DataAddr_Lo,
DataAddr_Hi, Ins, dl, DAG, InVals);
}
bool PIC16TargetLowering::isDirectLoad(const SDValue Op) {
@ -1660,17 +1586,19 @@ void PIC16TargetLowering::InitReservedFrameCount(const Function *F) {
ReservedFrameCount = NumArgs + 1;
}
// LowerFORMAL_ARGUMENTS - Argument values are loaded from the
// LowerFormalArguments - Argument values are loaded from the
// <fname>.args + offset. All arguments are already broken to leaglized
// types, so the offset just runs from 0 to NumArgVals - 1.
SDValue PIC16TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
SelectionDAG &DAG) {
SmallVector<SDValue, 8> ArgValues;
unsigned NumArgVals = Op.getNode()->getNumValues() - 1;
DebugLoc dl = Op.getDebugLoc();
SDValue Chain = Op.getOperand(0); // Formal arguments' chain
SDValue
PIC16TargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
unsigned NumArgVals = Ins.size();
// Get the callee's name to create the <fname>.args label to pass args.
MachineFunction &MF = DAG.getMachineFunction();
@ -1694,13 +1622,10 @@ SDValue PIC16TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
SDValue PICLoad = DAG.getNode(PIC16ISD::PIC16LdArg, dl, VTs, Chain, ES, BS,
Offset);
Chain = getChain(PICLoad);
ArgValues.push_back(PICLoad);
InVals.push_back(PICLoad);
}
// Return a MERGE_VALUE node.
ArgValues.push_back(Op.getOperand(0));
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
// Perform DAGCombine of PIC16Load.

View File

@ -52,6 +52,7 @@ namespace llvm {
SUBCC, // Compare for equality or inequality.
SELECT_ICC, // Psuedo to be caught in schedular and expanded to brcond.
BRCOND, // Conditional branch.
RET, // Return.
Dummy
};
@ -82,32 +83,35 @@ namespace llvm {
virtual const char *getTargetNodeName(unsigned Opcode) const;
/// getSetCCResultType - Return the ISD::SETCC ValueType
virtual MVT getSetCCResultType(MVT ValType) const;
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerShift(SDValue Op, SelectionDAG &DAG);
SDValue LowerMUL(SDValue Op, SelectionDAG &DAG);
SDValue LowerADD(SDValue Op, SelectionDAG &DAG);
SDValue LowerSUB(SDValue Op, SelectionDAG &DAG);
SDValue LowerBinOp(SDValue Op, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
// Call returns
SDValue
LowerDirectCallReturn(SDValue Op, SDValue Chain, SDValue FrameAddress,
SDValue InFlag, SelectionDAG &DAG);
LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue
LowerIndirectCallReturn(SDValue Op, SDValue Chain, SDValue InFlag,
SDValue DataAddr_Lo, SDValue DataAddr_Hi,
SelectionDAG &DAG);
LowerIndirectCallReturn(SDValue Chain, SDValue InFlag,
SDValue DataAddr_Lo, SDValue DataAddr_Hi,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
// Call arguments
SDValue
LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue FrameAddress,
SDValue InFlag, SelectionDAG &DAG);
LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
SDValue
LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag,
LowerIndirectCallArguments(SDValue Chain, SDValue InFlag,
SDValue DataAddr_Lo, SDValue DataAddr_Hi,
SelectionDAG &DAG);
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
@ -125,6 +129,28 @@ namespace llvm {
SmallVectorImpl<SDValue> &Results,
SelectionDAG &DAG);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
SDValue ExpandStore(SDNode *N, SelectionDAG &DAG);
SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG);
SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
@ -175,12 +201,6 @@ namespace llvm {
void LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, SDValue &ES,
int &Offset);
// CALL node should have all legal operands only. Legalize all non-legal
// operands of CALL node and then return the new call will all operands
// legal.
SDValue LegalizeCALL(SDValue Op, SelectionDAG &DAG);
// For indirect calls data address of the callee frame need to be
// extracted. This function fills the arguments DataAddr_Lo and
// DataAddr_Hi with the address of the callee frame.

View File

@ -115,6 +115,8 @@ def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond,
def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc,
[SDNPInFlag]>;
def PIC16ret : SDNode<"PIC16ISD::RET", SDTNone, [SDNPHasChain]>;
//===----------------------------------------------------------------------===//
// PIC16 Operand Definitions.
//===----------------------------------------------------------------------===//
@ -493,7 +495,7 @@ def pagesel :
// Return insn.
let isTerminator = 1, isBarrier = 1, isReturn = 1 in
def Return :
ControlFormat<0, (outs), (ins), "return", [(ret)]>;
ControlFormat<0, (outs), (ins), "return", [(PIC16ret)]>;
//===----------------------------------------------------------------------===//
// PIC16 Replacment Patterns.

View File

@ -203,9 +203,6 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
// RET must be custom lowered, to meet ABI requirements.
setOperationAction(ISD::RET , MVT::Other, Custom);
// TRAP is legal.
setOperationAction(ISD::TRAP, MVT::Other, Legal);
@ -448,7 +445,6 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
case PPCISD::MTFSB1: return "PPCISD::MTFSB1";
case PPCISD::FADDRTZ: return "PPCISD::FADDRTZ";
case PPCISD::MTFSF: return "PPCISD::MTFSF";
case PPCISD::TAILCALL: return "PPCISD::TAILCALL";
case PPCISD::TC_RETURN: return "PPCISD::TC_RETURN";
}
}
@ -1293,6 +1289,7 @@ SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) {
std::pair<SDValue, SDValue> CallResult =
LowerCallTo(Chain, Op.getValueType().getTypeForMVT(),
false, false, false, false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
DAG.getExternalSymbol("__trampoline_setup", PtrVT),
Args, DAG, dl);
@ -1472,9 +1469,8 @@ static const unsigned *GetFPR(const PPCSubtarget &Subtarget) {
/// CalculateStackSlotSize - Calculates the size reserved for this argument on
/// the stack.
static unsigned CalculateStackSlotSize(SDValue Arg, ISD::ArgFlagsTy Flags,
static unsigned CalculateStackSlotSize(MVT ArgVT, ISD::ArgFlagsTy Flags,
unsigned PtrByteSize) {
MVT ArgVT = Arg.getValueType();
unsigned ArgSize = ArgVT.getSizeInBits()/8;
if (Flags.isByVal())
ArgSize = Flags.getByValSize();
@ -1484,13 +1480,30 @@ static unsigned CalculateStackSlotSize(SDValue Arg, ISD::ArgFlagsTy Flags,
}
SDValue
PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
SelectionDAG &DAG,
int &VarArgsFrameIndex,
int &VarArgsStackOffset,
unsigned &VarArgsNumGPR,
unsigned &VarArgsNumFPR,
const PPCSubtarget &Subtarget) {
PPCTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
if (PPCSubTarget.isSVR4ABI()) {
return LowerFormalArguments_SVR4(Chain, CallConv, isVarArg, Ins,
dl, DAG, InVals);
} else {
return LowerFormalArguments_Darwin(Chain, CallConv, isVarArg, Ins,
dl, DAG, InVals);
}
}
SDValue
PPCTargetLowering::LowerFormalArguments_SVR4(
SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// SVR4 ABI Stack Frame Layout:
// +-----------------------------------+
// +--> | Back chain |
@ -1522,25 +1535,21 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
SmallVector<SDValue, 8> ArgValues;
SDValue Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
DebugLoc dl = Op.getDebugLoc();
MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
// Potential tail calls could cause overwriting of argument stack slots.
unsigned CC = MF.getFunction()->getCallingConv();
bool isImmutable = !(PerformTailCallOpt && (CC==CallingConv::Fast));
bool isImmutable = !(PerformTailCallOpt && (CallConv==CallingConv::Fast));
unsigned PtrByteSize = 4;
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
*DAG.getContext());
// Reserve space for the linkage area on the stack.
CCInfo.AllocateStack(PPCFrameInfo::getLinkageSize(false, false), PtrByteSize);
CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_PPC_SVR4);
CCInfo.AnalyzeFormalArguments(Ins, CC_PPC_SVR4);
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
@ -1552,7 +1561,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
switch (ValVT.getSimpleVT()) {
default:
llvm_unreachable("ValVT not supported by FORMAL_ARGUMENTS Lowering");
llvm_unreachable("ValVT not supported by formal arguments Lowering");
case MVT::i32:
RC = PPC::GPRCRegisterClass;
break;
@ -1572,9 +1581,9 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
// Transform the arguments stored in physical registers into virtual ones.
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, ValVT);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, ValVT);
ArgValues.push_back(ArgValue);
InVals.push_back(ArgValue);
} else {
// Argument stored in memory.
assert(VA.isMemLoc());
@ -1585,7 +1594,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
// Create load nodes to retrieve arguments from the stack.
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
ArgValues.push_back(DAG.getLoad(VA.getValVT(), dl, Root, FIN, NULL, 0));
InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0));
}
}
@ -1593,13 +1602,13 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
// Aggregates passed by value are stored in the local variable space of the
// caller's stack frame, right above the parameter list area.
SmallVector<CCValAssign, 16> ByValArgLocs;
CCState CCByValInfo(CC, isVarArg, getTargetMachine(),
CCState CCByValInfo(CallConv, isVarArg, getTargetMachine(),
ByValArgLocs, *DAG.getContext());
// Reserve stack space for the allocations in CCInfo.
CCByValInfo.AllocateStack(CCInfo.getNextStackOffset(), PtrByteSize);
CCByValInfo.AnalyzeFormalArguments(Op.getNode(), CC_PPC_SVR4_ByVal);
CCByValInfo.AnalyzeFormalArguments(Ins, CC_PPC_SVR4_ByVal);
// Area that is at least reserved in the caller of this function.
unsigned MinReservedArea = CCByValInfo.getNextStackOffset();
@ -1656,7 +1665,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
unsigned GPRIndex = 0;
for (; GPRIndex != VarArgsNumGPR; ++GPRIndex) {
SDValue Val = DAG.getRegister(GPArgRegs[GPRIndex], PtrVT);
SDValue Store = DAG.getStore(Root, dl, Val, FIN, NULL, 0);
SDValue Store = DAG.getStore(Chain, dl, Val, FIN, NULL, 0);
MemOps.push_back(Store);
// Increment the address by four for the next argument to store
SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
@ -1669,7 +1678,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
for (; GPRIndex != NumGPArgRegs; ++GPRIndex) {
unsigned VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, PtrVT);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0);
MemOps.push_back(Store);
// Increment the address by four for the next argument to store
@ -1685,7 +1694,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
unsigned FPRIndex = 0;
for (FPRIndex = 0; FPRIndex != VarArgsNumFPR; ++FPRIndex) {
SDValue Val = DAG.getRegister(FPArgRegs[FPRIndex], MVT::f64);
SDValue Store = DAG.getStore(Root, dl, Val, FIN, NULL, 0);
SDValue Store = DAG.getStore(Chain, dl, Val, FIN, NULL, 0);
MemOps.push_back(Store);
// Increment the address by eight for the next argument to store
SDValue PtrOff = DAG.getConstant(MVT(MVT::f64).getSizeInBits()/8,
@ -1696,7 +1705,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
for (; FPRIndex != NumFPArgRegs; ++FPRIndex) {
unsigned VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::f64);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::f64);
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0);
MemOps.push_back(Store);
// Increment the address by eight for the next argument to store
@ -1707,36 +1716,30 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op,
}
if (!MemOps.empty())
Root = DAG.getNode(ISD::TokenFactor, dl,
MVT::Other, &MemOps[0], MemOps.size());
Chain = DAG.getNode(ISD::TokenFactor, dl,
MVT::Other, &MemOps[0], MemOps.size());
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
SDValue
PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
SelectionDAG &DAG,
int &VarArgsFrameIndex,
const PPCSubtarget &Subtarget) {
PPCTargetLowering::LowerFormalArguments_Darwin(
SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// TODO: add description of PPC stack frame format, or at least some docs.
//
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
SmallVector<SDValue, 8> ArgValues;
SDValue Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
DebugLoc dl = Op.getDebugLoc();
MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
bool isPPC64 = PtrVT == MVT::i64;
// Potential tail calls could cause overwriting of argument stack slots.
unsigned CC = MF.getFunction()->getCallingConv();
bool isImmutable = !(PerformTailCallOpt && (CC==CallingConv::Fast));
bool isImmutable = !(PerformTailCallOpt && (CallConv==CallingConv::Fast));
unsigned PtrByteSize = isPPC64 ? 8 : 4;
unsigned ArgOffset = PPCFrameInfo::getLinkageSize(isPPC64, true);
@ -1752,7 +1755,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
PPC::X7, PPC::X8, PPC::X9, PPC::X10,
};
static const unsigned *FPR = GetFPR(Subtarget);
static const unsigned *FPR = GetFPR(PPCSubTarget);
static const unsigned VR[] = {
PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
@ -1776,12 +1779,11 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
// entire point of the following loop.
unsigned VecArgOffset = ArgOffset;
if (!isVarArg && !isPPC64) {
for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues()-1; ArgNo != e;
for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e;
++ArgNo) {
MVT ObjectVT = Op.getValue(ArgNo).getValueType();
MVT ObjectVT = Ins[ArgNo].VT;
unsigned ObjSize = ObjectVT.getSizeInBits()/8;
ISD::ArgFlagsTy Flags =
cast<ARG_FLAGSSDNode>(Op.getOperand(ArgNo+3))->getArgFlags();
ISD::ArgFlagsTy Flags = Ins[ArgNo].Flags;
if (Flags.isByVal()) {
// ObjSize is the true size, ArgSize rounded up to multiple of regs.
@ -1822,15 +1824,13 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
SmallVector<SDValue, 8> MemOps;
unsigned nAltivecParamsAtEnd = 0;
for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
ArgNo != e; ++ArgNo) {
for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
SDValue ArgVal;
bool needsLoad = false;
MVT ObjectVT = Op.getValue(ArgNo).getValueType();
MVT ObjectVT = Ins[ArgNo].VT;
unsigned ObjSize = ObjectVT.getSizeInBits()/8;
unsigned ArgSize = ObjSize;
ISD::ArgFlagsTy Flags =
cast<ARG_FLAGSSDNode>(Op.getOperand(ArgNo+3))->getArgFlags();
ISD::ArgFlagsTy Flags = Ins[ArgNo].Flags;
unsigned CurArgOffset = ArgOffset;
@ -1839,13 +1839,13 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
ObjectVT==MVT::v8i16 || ObjectVT==MVT::v16i8) {
if (isVarArg || isPPC64) {
MinReservedArea = ((MinReservedArea+15)/16)*16;
MinReservedArea += CalculateStackSlotSize(Op.getValue(ArgNo),
MinReservedArea += CalculateStackSlotSize(ObjectVT,
Flags,
PtrByteSize);
} else nAltivecParamsAtEnd++;
} else
// Calculate min reserved area.
MinReservedArea += CalculateStackSlotSize(Op.getValue(ArgNo),
MinReservedArea += CalculateStackSlotSize(Ins[ArgNo].VT,
Flags,
PtrByteSize);
@ -1863,11 +1863,11 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
// The value of the object is its address.
int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset);
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
ArgValues.push_back(FIN);
InVals.push_back(FIN);
if (ObjSize==1 || ObjSize==2) {
if (GPR_idx != Num_GPR_Regs) {
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, PtrVT);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN,
NULL, 0, ObjSize==1 ? MVT::i8 : MVT::i16 );
MemOps.push_back(Store);
@ -1886,7 +1886,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset);
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, PtrVT);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0);
MemOps.push_back(Store);
++GPR_idx;
@ -1905,7 +1905,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
if (!isPPC64) {
if (GPR_idx != Num_GPR_Regs) {
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
ArgVal = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
++GPR_idx;
} else {
needsLoad = true;
@ -1919,7 +1919,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
case MVT::i64: // PPC64
if (GPR_idx != Num_GPR_Regs) {
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass);
ArgVal = DAG.getCopyFromReg(Root, dl, VReg, MVT::i64);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64);
if (ObjectVT == MVT::i32) {
// PPC64 passes i8, i16, and i32 values in i64 registers. Promote
@ -1960,7 +1960,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
else
VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass);
ArgVal = DAG.getCopyFromReg(Root, dl, VReg, ObjectVT);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
++FPR_idx;
} else {
needsLoad = true;
@ -1977,7 +1977,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
// except in varargs functions.
if (VR_idx != Num_VR_Regs) {
unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass);
ArgVal = DAG.getCopyFromReg(Root, dl, VReg, ObjectVT);
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
if (isVarArg) {
while ((ArgOffset % 16) != 0) {
ArgOffset += PtrByteSize;
@ -2011,10 +2011,10 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
CurArgOffset + (ArgSize - ObjSize),
isImmutable);
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
ArgVal = DAG.getLoad(ObjectVT, dl, Root, FIN, NULL, 0);
ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0);
}
ArgValues.push_back(ArgVal);
InVals.push_back(ArgVal);
}
// Set the size that is at least reserved in caller of this function. Tail
@ -2056,7 +2056,7 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
else
VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, PtrVT);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0);
MemOps.push_back(Store);
// Increment the address by four for the next argument to store
@ -2066,14 +2066,10 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op,
}
if (!MemOps.empty())
Root = DAG.getNode(ISD::TokenFactor, dl,
MVT::Other, &MemOps[0], MemOps.size());
Chain = DAG.getNode(ISD::TokenFactor, dl,
MVT::Other, &MemOps[0], MemOps.size());
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size());
return Chain;
}
/// CalculateParameterAndLinkageAreaSize - Get the size of the paramter plus
@ -2083,13 +2079,14 @@ CalculateParameterAndLinkageAreaSize(SelectionDAG &DAG,
bool isPPC64,
bool isVarArg,
unsigned CC,
CallSDNode *TheCall,
const SmallVectorImpl<ISD::OutputArg>
&Outs,
unsigned &nAltivecParamsAtEnd) {
// Count how many bytes are to be pushed on the stack, including the linkage
// area, and parameter passing area. We start with 24/48 bytes, which is
// prereserved space for [SP][CR][LR][3 x unused].
unsigned NumBytes = PPCFrameInfo::getLinkageSize(isPPC64, true);
unsigned NumOps = TheCall->getNumArgs();
unsigned NumOps = Outs.size();
unsigned PtrByteSize = isPPC64 ? 8 : 4;
// Add up all the space actually used.
@ -2100,8 +2097,8 @@ CalculateParameterAndLinkageAreaSize(SelectionDAG &DAG,
// 16-byte aligned.
nAltivecParamsAtEnd = 0;
for (unsigned i = 0; i != NumOps; ++i) {
SDValue Arg = TheCall->getArg(i);
ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i);
SDValue Arg = Outs[i].Val;
ISD::ArgFlagsTy Flags = Outs[i].Flags;
MVT ArgVT = Arg.getValueType();
// Varargs Altivec parameters are padded to a 16 byte boundary.
if (ArgVT==MVT::v4f32 || ArgVT==MVT::v4i32 ||
@ -2115,7 +2112,7 @@ CalculateParameterAndLinkageAreaSize(SelectionDAG &DAG,
// Varargs and 64-bit Altivec parameters are padded to 16 byte boundary.
NumBytes = ((NumBytes+15)/16)*16;
}
NumBytes += CalculateStackSlotSize(Arg, Flags, PtrByteSize);
NumBytes += CalculateStackSlotSize(ArgVT, Flags, PtrByteSize);
}
// Allow for Altivec parameters at the end, if needed.
@ -2160,40 +2157,37 @@ static int CalculateTailCallSPDiff(SelectionDAG& DAG, bool IsTailCall,
return SPDiff;
}
/// IsEligibleForTailCallElimination - Check to see whether the next instruction
/// following the call is a return. A function is eligible if caller/callee
/// calling conventions match, currently only fastcc supports tail calls, and
/// the function CALL is immediatly followed by a RET.
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
/// for tail call optimization. Targets which want to do tail call
/// optimization should implement this function.
bool
PPCTargetLowering::IsEligibleForTailCallOptimization(CallSDNode *TheCall,
SDValue Ret,
PPCTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
unsigned CalleeCC,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SelectionDAG& DAG) const {
// Variable argument functions are not supported.
if (!PerformTailCallOpt || TheCall->isVarArg())
if (isVarArg)
return false;
if (CheckTailCallReturnConstraints(TheCall, Ret)) {
MachineFunction &MF = DAG.getMachineFunction();
unsigned CallerCC = MF.getFunction()->getCallingConv();
unsigned CalleeCC = TheCall->getCallingConv();
if (CalleeCC == CallingConv::Fast && CallerCC == CalleeCC) {
// Functions containing by val parameters are not supported.
for (unsigned i = 0; i != TheCall->getNumArgs(); i++) {
ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i);
if (Flags.isByVal()) return false;
}
SDValue Callee = TheCall->getCallee();
// Non PIC/GOT tail calls are supported.
if (getTargetMachine().getRelocationModel() != Reloc::PIC_)
return true;
// At the moment we can only do local tail calls (in same module, hidden
// or protected) if we are generating PIC.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
return G->getGlobal()->hasHiddenVisibility()
|| G->getGlobal()->hasProtectedVisibility();
MachineFunction &MF = DAG.getMachineFunction();
unsigned CallerCC = MF.getFunction()->getCallingConv();
if (CalleeCC == CallingConv::Fast && CallerCC == CalleeCC) {
// Functions containing by val parameters are not supported.
for (unsigned i = 0; i != Ins.size(); i++) {
ISD::ArgFlagsTy Flags = Ins[i].Flags;
if (Flags.isByVal()) return false;
}
// Non PIC/GOT tail calls are supported.
if (getTargetMachine().getRelocationModel() != Reloc::PIC_)
return true;
// At the moment we can only do local tail calls (in same module, hidden
// or protected) if we are generating PIC.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
return G->getGlobal()->hasHiddenVisibility()
|| G->getGlobal()->hasProtectedVisibility();
}
return false;
@ -2455,16 +2449,17 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
return CallOpc;
}
static SDValue LowerCallReturn(SDValue Op, SelectionDAG &DAG, TargetMachine &TM,
CallSDNode *TheCall, SDValue Chain,
SDValue InFlag) {
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = TheCall->getDebugLoc();
SmallVector<SDValue, 16> ResultVals;
SDValue
PPCTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
SmallVector<CCValAssign, 16> RVLocs;
unsigned CallerCC = DAG.getMachineFunction().getFunction()->getCallingConv();
CCState CCRetInfo(CallerCC, isVarArg, TM, RVLocs, *DAG.getContext());
CCRetInfo.AnalyzeCallResult(TheCall, RetCC_PPC);
CCState CCRetInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCRetInfo.AnalyzeCallResult(Ins, RetCC_PPC);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
@ -2473,53 +2468,61 @@ static SDValue LowerCallReturn(SDValue Op, SelectionDAG &DAG, TargetMachine &TM,
assert(VA.isRegLoc() && "Can only return in registers!");
Chain = DAG.getCopyFromReg(Chain, dl,
VA.getLocReg(), VT, InFlag).getValue(1);
ResultVals.push_back(Chain.getValue(0));
InVals.push_back(Chain.getValue(0));
InFlag = Chain.getValue(2);
}
// If the function returns void, just return the chain.
if (RVLocs.empty())
return Chain;
// Otherwise, merge everything together with a MERGE_VALUES node.
ResultVals.push_back(Chain);
SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
&ResultVals[0], ResultVals.size());
return Res.getValue(Op.getResNo());
return Chain;
}
static
SDValue FinishCall(SelectionDAG &DAG, CallSDNode *TheCall, TargetMachine &TM,
SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass,
SDValue Op, SDValue InFlag, SDValue Chain, SDValue &Callee,
int SPDiff, unsigned NumBytes) {
unsigned CC = TheCall->getCallingConv();
DebugLoc dl = TheCall->getDebugLoc();
bool isTailCall = TheCall->isTailCall()
&& CC == CallingConv::Fast && PerformTailCallOpt;
SDValue
PPCTargetLowering::FinishCall(unsigned CallConv, DebugLoc dl, bool isTailCall,
bool isVarArg,
SelectionDAG &DAG,
SmallVector<std::pair<unsigned, SDValue>, 8>
&RegsToPass,
SDValue InFlag, SDValue Chain,
SDValue &Callee,
int SPDiff, unsigned NumBytes,
const SmallVectorImpl<ISD::InputArg> &Ins,
SmallVectorImpl<SDValue> &InVals) {
std::vector<MVT> NodeTys;
SmallVector<SDValue, 8> Ops;
unsigned CallOpc = PrepareCall(DAG, Callee, InFlag, Chain, dl, SPDiff,
isTailCall, RegsToPass, Ops, NodeTys,
TM.getSubtarget<PPCSubtarget>().isSVR4ABI());
PPCSubTarget.isSVR4ABI());
// When performing tail call optimization the callee pops its arguments off
// the stack. Account for this here so these bytes can be pushed back on in
// PPCRegisterInfo::eliminateCallFramePseudoInstr.
int BytesCalleePops =
(CC==CallingConv::Fast && PerformTailCallOpt) ? NumBytes : 0;
(CallConv==CallingConv::Fast && PerformTailCallOpt) ? NumBytes : 0;
if (InFlag.getNode())
Ops.push_back(InFlag);
// Emit tail call.
if (isTailCall) {
assert(InFlag.getNode() &&
"Flag must be set. Depend on flag being set in LowerRET");
Chain = DAG.getNode(PPCISD::TAILCALL, dl,
TheCall->getVTList(), &Ops[0], Ops.size());
return SDValue(Chain.getNode(), Op.getResNo());
// If this is the first return lowered for this function, add the regs
// to the liveout set for the function.
if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs,
*DAG.getContext());
CCInfo.AnalyzeCallResult(Ins, RetCC_PPC);
for (unsigned i = 0; i != RVLocs.size(); ++i)
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
assert(((Callee.getOpcode() == ISD::Register &&
cast<RegisterSDNode>(Callee)->getReg() == PPC::CTR) ||
Callee.getOpcode() == ISD::TargetExternalSymbol ||
Callee.getOpcode() == ISD::TargetGlobalAddress ||
isa<ConstantSDNode>(Callee)) &&
"Expecting an global address, external symbol, absolute value or register");
return DAG.getNode(PPCISD::TC_RETURN, dl, MVT::Other, &Ops[0], Ops.size());
}
Chain = DAG.getNode(CallOpc, dl, NodeTys, &Ops[0], Ops.size());
@ -2528,27 +2531,49 @@ SDValue FinishCall(SelectionDAG &DAG, CallSDNode *TheCall, TargetMachine &TM,
Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
DAG.getIntPtrConstant(BytesCalleePops, true),
InFlag);
if (TheCall->getValueType(0) != MVT::Other)
if (!Ins.empty())
InFlag = Chain.getValue(1);
return LowerCallReturn(Op, DAG, TM, TheCall, Chain, InFlag);
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
Ins, dl, DAG, InVals);
}
SDValue PPCTargetLowering::LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget,
TargetMachine &TM) {
// See PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4() for a description
SDValue
PPCTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
if (PPCSubTarget.isSVR4ABI()) {
return LowerCall_SVR4(Chain, Callee, CallConv, isVarArg,
isTailCall, Outs, Ins,
dl, DAG, InVals);
} else {
return LowerCall_Darwin(Chain, Callee, CallConv, isVarArg,
isTailCall, Outs, Ins,
dl, DAG, InVals);
}
}
SDValue
PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// See PPCTargetLowering::LowerFormalArguments_SVR4() for a description
// of the SVR4 ABI stack frame layout.
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
bool isVarArg = TheCall->isVarArg();
unsigned CC = TheCall->getCallingConv();
assert((CC == CallingConv::C ||
CC == CallingConv::Fast) && "Unknown calling convention!");
bool isTailCall = TheCall->isTailCall()
&& CC == CallingConv::Fast && PerformTailCallOpt;
SDValue Callee = TheCall->getCallee();
DebugLoc dl = TheCall->getDebugLoc();
assert((!isTailCall ||
(CallConv == CallingConv::Fast && PerformTailCallOpt)) &&
"IsEligibleForTailCallOptimization missed a case!");
assert((CallConv == CallingConv::C ||
CallConv == CallingConv::Fast) && "Unknown calling convention!");
MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
unsigned PtrByteSize = 4;
@ -2560,7 +2585,7 @@ SDValue PPCTargetLowering::LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG,
// and restoring the callers stack pointer in this functions epilog. This is
// done because by tail calling the called function might overwrite the value
// in this function's (MF) stack pointer stack slot 0(SP).
if (PerformTailCallOpt && CC==CallingConv::Fast)
if (PerformTailCallOpt && CallConv==CallingConv::Fast)
MF.getInfo<PPCFunctionInfo>()->setHasFastCall();
// Count how many bytes are to be pushed on the stack, including the linkage
@ -2569,7 +2594,8 @@ SDValue PPCTargetLowering::LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG,
// Assign locations to all of the outgoing arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
// Reserve space for the linkage area on the stack.
CCInfo.AllocateStack(PPCFrameInfo::getLinkageSize(false, false), PtrByteSize);
@ -2578,15 +2604,14 @@ SDValue PPCTargetLowering::LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG,
// Handle fixed and variable vector arguments differently.
// Fixed vector arguments go into registers as long as registers are
// available. Variable vector arguments always go into memory.
unsigned NumArgs = TheCall->getNumArgs();
unsigned NumFixedArgs = TheCall->getNumFixedArgs();
unsigned NumArgs = Outs.size();
for (unsigned i = 0; i != NumArgs; ++i) {
MVT ArgVT = TheCall->getArg(i).getValueType();
ISD::ArgFlagsTy ArgFlags = TheCall->getArgFlags(i);
MVT ArgVT = Outs[i].Val.getValueType();
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
bool Result;
if (i < NumFixedArgs) {
if (Outs[i].IsFixed) {
Result = CC_PPC_SVR4(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags,
CCInfo);
} else {
@ -2604,18 +2629,18 @@ SDValue PPCTargetLowering::LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG,
}
} else {
// All arguments are treated the same.
CCInfo.AnalyzeCallOperands(TheCall, CC_PPC_SVR4);
CCInfo.AnalyzeCallOperands(Outs, CC_PPC_SVR4);
}
// Assign locations to all of the outgoing aggregate by value arguments.
SmallVector<CCValAssign, 16> ByValArgLocs;
CCState CCByValInfo(CC, isVarArg, getTargetMachine(), ByValArgLocs,
CCState CCByValInfo(CallConv, isVarArg, getTargetMachine(), ByValArgLocs,
*DAG.getContext());
// Reserve stack space for the allocations in CCInfo.
CCByValInfo.AllocateStack(CCInfo.getNextStackOffset(), PtrByteSize);
CCByValInfo.AnalyzeCallOperands(TheCall, CC_PPC_SVR4_ByVal);
CCByValInfo.AnalyzeCallOperands(Outs, CC_PPC_SVR4_ByVal);
// Size of the linkage area, parameter list area and the part of the local
// space variable where copies of aggregates which are passed by value are
@ -2651,8 +2676,8 @@ SDValue PPCTargetLowering::LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG,
i != e;
++i) {
CCValAssign &VA = ArgLocs[i];
SDValue Arg = TheCall->getArg(i);
ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i);
SDValue Arg = Outs[i].Val;
ISD::ArgFlagsTy Flags = Outs[i].Flags;
if (Flags.isByVal()) {
// Argument is an aggregate which is passed by value, thus we need to
@ -2736,22 +2761,21 @@ SDValue PPCTargetLowering::LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG,
false, TailCallArguments);
}
return FinishCall(DAG, TheCall, TM, RegsToPass, Op, InFlag, Chain, Callee,
SPDiff, NumBytes);
return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG,
RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes,
Ins, InVals);
}
SDValue PPCTargetLowering::LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget,
TargetMachine &TM) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
bool isVarArg = TheCall->isVarArg();
unsigned CC = TheCall->getCallingConv();
bool isTailCall = TheCall->isTailCall()
&& CC == CallingConv::Fast && PerformTailCallOpt;
SDValue Callee = TheCall->getCallee();
unsigned NumOps = TheCall->getNumArgs();
DebugLoc dl = TheCall->getDebugLoc();
SDValue
PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
unsigned NumOps = Outs.size();
MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
bool isPPC64 = PtrVT == MVT::i64;
@ -2764,7 +2788,7 @@ SDValue PPCTargetLowering::LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG,
// and restoring the callers stack pointer in this functions epilog. This is
// done because by tail calling the called function might overwrite the value
// in this function's (MF) stack pointer stack slot 0(SP).
if (PerformTailCallOpt && CC==CallingConv::Fast)
if (PerformTailCallOpt && CallConv==CallingConv::Fast)
MF.getInfo<PPCFunctionInfo>()->setHasFastCall();
unsigned nAltivecParamsAtEnd = 0;
@ -2773,13 +2797,19 @@ SDValue PPCTargetLowering::LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG,
// area, and parameter passing area. We start with 24/48 bytes, which is
// prereserved space for [SP][CR][LR][3 x unused].
unsigned NumBytes =
CalculateParameterAndLinkageAreaSize(DAG, isPPC64, isVarArg, CC, TheCall,
CalculateParameterAndLinkageAreaSize(DAG, isPPC64, isVarArg, CallConv,
Outs,
nAltivecParamsAtEnd);
// Calculate by how many bytes the stack has to be adjusted in case of tail
// call optimization.
int SPDiff = CalculateTailCallSPDiff(DAG, isTailCall, NumBytes);
// To protect arguments on the stack from being clobbered in a tail call,
// force all the loads to happen before doing any other lowering.
if (isTailCall)
Chain = DAG.getStackArgumentTokenFactor(Chain);
// Adjust the stack pointer for the new arguments...
// These operations are automatically eliminated by the prolog/epilog pass
Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true));
@ -2815,7 +2845,7 @@ SDValue PPCTargetLowering::LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG,
PPC::X3, PPC::X4, PPC::X5, PPC::X6,
PPC::X7, PPC::X8, PPC::X9, PPC::X10,
};
static const unsigned *FPR = GetFPR(Subtarget);
static const unsigned *FPR = GetFPR(PPCSubTarget);
static const unsigned VR[] = {
PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
@ -2833,8 +2863,8 @@ SDValue PPCTargetLowering::LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG,
SmallVector<SDValue, 8> MemOpChains;
for (unsigned i = 0; i != NumOps; ++i) {
bool inMem = false;
SDValue Arg = TheCall->getArg(i);
ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i);
SDValue Arg = Outs[i].Val;
ISD::ArgFlagsTy Flags = Outs[i].Flags;
// PtrOff will be used to store the current argument to the stack if a
// register cannot be found for it.
@ -3031,7 +3061,7 @@ SDValue PPCTargetLowering::LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG,
ArgOffset = ((ArgOffset+15)/16)*16;
ArgOffset += 12*16;
for (unsigned i = 0; i != NumOps; ++i) {
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
MVT ArgType = Arg.getValueType();
if (ArgType==MVT::v4f32 || ArgType==MVT::v4i32 ||
ArgType==MVT::v8i16 || ArgType==MVT::v16i8) {
@ -3065,18 +3095,21 @@ SDValue PPCTargetLowering::LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG,
FPOp, true, TailCallArguments);
}
return FinishCall(DAG, TheCall, TM, RegsToPass, Op, InFlag, Chain, Callee,
SPDiff, NumBytes);
return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG,
RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes,
Ins, InVals);
}
SDValue PPCTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG,
TargetMachine &TM) {
SDValue
PPCTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
DebugLoc dl = Op.getDebugLoc();
CCState CCInfo(CC, isVarArg, TM, RVLocs, *DAG.getContext());
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_PPC);
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCInfo.AnalyzeReturn(Outs, RetCC_PPC);
// If this is the first return lowered for this function, add the regs to the
// liveout set for the function.
@ -3085,37 +3118,6 @@ SDValue PPCTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG,
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
SDValue Chain = Op.getOperand(0);
Chain = GetPossiblePreceedingTailCall(Chain, PPCISD::TAILCALL);
if (Chain.getOpcode() == PPCISD::TAILCALL) {
SDValue TailCall = Chain;
SDValue TargetAddress = TailCall.getOperand(1);
SDValue StackAdjustment = TailCall.getOperand(2);
assert(((TargetAddress.getOpcode() == ISD::Register &&
cast<RegisterSDNode>(TargetAddress)->getReg() == PPC::CTR) ||
TargetAddress.getOpcode() == ISD::TargetExternalSymbol ||
TargetAddress.getOpcode() == ISD::TargetGlobalAddress ||
isa<ConstantSDNode>(TargetAddress)) &&
"Expecting an global address, external symbol, absolute value or register");
assert(StackAdjustment.getOpcode() == ISD::Constant &&
"Expecting a const value");
SmallVector<SDValue,8> Operands;
Operands.push_back(Chain.getOperand(0));
Operands.push_back(TargetAddress);
Operands.push_back(StackAdjustment);
// Copy registers used by the call. Last operand is a flag so it is not
// copied.
for (unsigned i=3; i < TailCall.getNumOperands()-1; i++) {
Operands.push_back(Chain.getOperand(i));
}
return DAG.getNode(PPCISD::TC_RETURN, dl, MVT::Other, &Operands[0],
Operands.size());
}
SDValue Flag;
// Copy the result values into the output registers.
@ -3123,7 +3125,7 @@ SDValue PPCTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG,
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Op.getOperand(i*2+1), Flag);
Outs[i].Val, Flag);
Flag = Chain.getValue(1);
}
@ -4178,24 +4180,6 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
return LowerVAARG(Op, DAG, VarArgsFrameIndex, VarArgsStackOffset,
VarArgsNumGPR, VarArgsNumFPR, PPCSubTarget);
case ISD::FORMAL_ARGUMENTS:
if (PPCSubTarget.isSVR4ABI()) {
return LowerFORMAL_ARGUMENTS_SVR4(Op, DAG, VarArgsFrameIndex,
VarArgsStackOffset, VarArgsNumGPR,
VarArgsNumFPR, PPCSubTarget);
} else {
return LowerFORMAL_ARGUMENTS_Darwin(Op, DAG, VarArgsFrameIndex,
PPCSubTarget);
}
case ISD::CALL:
if (PPCSubTarget.isSVR4ABI()) {
return LowerCALL_SVR4(Op, DAG, PPCSubTarget, getTargetMachine());
} else {
return LowerCALL_Darwin(Op, DAG, PPCSubTarget, getTargetMachine());
}
case ISD::RET: return LowerRET(Op, DAG, getTargetMachine());
case ISD::STACKRESTORE: return LowerSTACKRESTORE(Op, DAG, PPCSubTarget);
case ISD::DYNAMIC_STACKALLOC:
return LowerDYNAMIC_STACKALLOC(Op, DAG, PPCSubTarget);

View File

@ -160,8 +160,6 @@ namespace llvm {
/// indexed. This is used to implement atomic operations.
STCX,
/// TAILCALL - Indicates a tail call should be taken.
TAILCALL,
/// TC_RETURN - A tail call return.
/// operand #0 chain
/// operand #1 callee (register or absolute)
@ -327,12 +325,12 @@ namespace llvm {
/// the offset of the target addressing mode.
virtual bool isLegalAddressImmediate(GlobalValue *GV) const;
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
/// for tail call optimization. Targets which want to do tail call
/// optimization should implement this function.
virtual bool IsEligibleForTailCallOptimization(CallSDNode *TheCall,
SDValue Ret,
SelectionDAG &DAG) const;
virtual bool
IsEligibleForTailCallOptimization(SDValue Callee,
unsigned CalleeCC,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SelectionDAG& DAG) const;
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
@ -370,20 +368,6 @@ namespace llvm {
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG, int VarArgsFrameIndex,
int VarArgsStackOffset, unsigned VarArgsNumGPR,
unsigned VarArgsNumFPR, const PPCSubtarget &Subtarget);
SDValue LowerFORMAL_ARGUMENTS_SVR4(SDValue Op, SelectionDAG &DAG,
int &VarArgsFrameIndex,
int &VarArgsStackOffset,
unsigned &VarArgsNumGPR,
unsigned &VarArgsNumFPR,
const PPCSubtarget &Subtarget);
SDValue LowerFORMAL_ARGUMENTS_Darwin(SDValue Op, SelectionDAG &DAG,
int &VarArgsFrameIndex,
const PPCSubtarget &Subtarget);
SDValue LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget, TargetMachine &TM);
SDValue LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget, TargetMachine &TM);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM);
SDValue LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget);
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG,
@ -400,6 +384,71 @@ namespace llvm {
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG);
SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG);
SDValue LowerMUL(SDValue Op, SelectionDAG &DAG);
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue FinishCall(unsigned CallConv, DebugLoc dl, bool isTailCall,
bool isVarArg,
SelectionDAG &DAG,
SmallVector<std::pair<unsigned, SDValue>, 8>
&RegsToPass,
SDValue InFlag, SDValue Chain,
SDValue &Callee,
int SPDiff, unsigned NumBytes,
const SmallVectorImpl<ISD::InputArg> &Ins,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
SDValue
LowerFormalArguments_Darwin(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue
LowerFormalArguments_SVR4(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue
LowerCall_Darwin(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue
LowerCall_SVR4(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
};
}

View File

@ -125,9 +125,6 @@ def retflag : SDNode<"PPCISD::RET_FLAG", SDTNone,
def PPCtc_return : SDNode<"PPCISD::TC_RETURN", SDT_PPCTC_ret,
[SDNPHasChain, SDNPOptInFlag]>;
def PPCtailcall : SDNode<"PPCISD::TAILCALL", SDT_PPCCall,
[SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
def PPCvcmp : SDNode<"PPCISD::VCMP" , SDT_PPCvcmp, []>;
def PPCvcmp_o : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp, [SDNPOutFlag]>;

View File

@ -33,18 +33,21 @@ using namespace llvm;
#include "SparcGenCallingConv.inc"
static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
SDValue
SparcTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
// CCValAssign - represent the assignment of the return value to locations.
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
DebugLoc dl = Op.getDebugLoc();
// CCState - Info about the registers and stack slot.
CCState CCInfo(CC, isVarArg, DAG.getTarget(), RVLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, DAG.getTarget(),
RVLocs, *DAG.getContext());
// Analize return values of ISD::RET
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_Sparc32);
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32);
// If this is the first return lowered for this function, add the regs to the
// liveout set for the function.
@ -54,7 +57,6 @@ static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
SDValue Chain = Op.getOperand(0);
SDValue Flag;
// Copy the result values into the output registers.
@ -62,10 +64,8 @@ static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
// ISD::RET => ret chain, (regnum1,val1), ...
// So i*2+1 index only the regnums.
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Op.getOperand(i*2+1), Flag);
Outs[i].Val, Flag);
// Guarantee that all emitted copies are stuck together with flags.
Flag = Chain.getValue(1);
@ -76,23 +76,25 @@ static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain);
}
/// LowerArguments - 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.
/// LowerFormalArguments - 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::LowerFORMAL_ARGUMENTS(SDValue Op,
SelectionDAG &DAG) {
SparcTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SDValue Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
unsigned CC = MF.getFunction()->getCallingConv();
DebugLoc dl = Op.getDebugLoc();
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_Sparc32);
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32);
static const unsigned ArgRegs[] = {
SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
@ -100,7 +102,6 @@ SparcTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
const unsigned *CurArgReg = ArgRegs, *ArgRegEnd = ArgRegs+6;
unsigned ArgOffset = 68;
SmallVector<SDValue, 16> ArgValues;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
SDValue ArgValue;
CCValAssign &VA = ArgLocs[i];
@ -113,23 +114,26 @@ SparcTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
case MVT::i8:
case MVT::i16:
case MVT::i32:
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
if (!Ins[i].Used) { // Argument is dead.
if (CurArgReg < ArgRegEnd) ++CurArgReg;
InVals.push_back(DAG.getUNDEF(ObjectVT));
} else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
SDValue Arg = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
if (ObjectVT != MVT::i32) {
unsigned AssertOp = ISD::AssertSext;
Arg = DAG.getNode(AssertOp, dl, MVT::i32, Arg,
DAG.getValueType(ObjectVT));
Arg = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Arg);
}
ArgValues.push_back(Arg);
InVals.push_back(Arg);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
SDValue Load;
if (ObjectVT == MVT::i32) {
Load = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
Load = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0);
} else {
ISD::LoadExtType LoadOp = ISD::SEXTLOAD;
@ -137,56 +141,63 @@ SparcTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
unsigned Offset = 4-std::max(1U, ObjectVT.getSizeInBits()/8);
FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr,
DAG.getConstant(Offset, MVT::i32));
Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Root, FIPtr,
Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Chain, FIPtr,
NULL, 0, ObjectVT);
Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load);
}
ArgValues.push_back(Load);
InVals.push_back(Load);
}
ArgOffset += 4;
break;
case MVT::f32:
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
if (!Ins[i].Used) { // Argument is dead.
if (CurArgReg < ArgRegEnd) ++CurArgReg;
InVals.push_back(DAG.getUNDEF(ObjectVT));
} else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
// FP value is passed in an integer register.
unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
SDValue Arg = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Arg);
ArgValues.push_back(Arg);
InVals.push_back(Arg);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
SDValue Load = DAG.getLoad(MVT::f32, dl, Root, FIPtr, NULL, 0);
ArgValues.push_back(Load);
SDValue Load = DAG.getLoad(MVT::f32, dl, Chain, FIPtr, NULL, 0);
InVals.push_back(Load);
}
ArgOffset += 4;
break;
case MVT::i64:
case MVT::f64:
{
if (!Ins[i].Used) { // Argument is dead.
if (CurArgReg < ArgRegEnd) ++CurArgReg;
if (CurArgReg < ArgRegEnd) ++CurArgReg;
InVals.push_back(DAG.getUNDEF(ObjectVT));
} else {
SDValue HiVal;
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg++, VRegHi);
HiVal = DAG.getCopyFromReg(Root, dl, VRegHi, MVT::i32);
HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
HiVal = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0);
}
SDValue LoVal;
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
unsigned VRegLo = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg++, VRegLo);
LoVal = DAG.getCopyFromReg(Root, dl, VRegLo, MVT::i32);
LoVal = DAG.getCopyFromReg(Chain, dl, VRegLo, MVT::i32);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4);
SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
LoVal = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0);
}
// Compose the two halves together into an i64 unit.
@ -197,7 +208,7 @@ SparcTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
if (ObjectVT == MVT::f64)
WholeValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, WholeValue);
ArgValues.push_back(WholeValue);
InVals.push_back(WholeValue);
}
ArgOffset += 8;
break;
@ -224,32 +235,29 @@ SparcTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
}
if (!OutChains.empty()) {
OutChains.push_back(Root);
Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&OutChains[0], OutChains.size());
OutChains.push_back(Chain);
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&OutChains[0], OutChains.size());
}
}
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
unsigned CallingConv = TheCall->getCallingConv();
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = TheCall->getDebugLoc();
SDValue
SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
#if 0
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallingConv, isVarArg, DAG.getTarget(), ArgLocs);
CCInfo.AnalyzeCallOperands(Op.getNode(), CC_Sparc32);
CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), ArgLocs);
CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32);
// Get the size of the outgoing arguments stack space requirement.
unsigned ArgsSize = CCInfo.getNextStackOffset();
@ -259,8 +267,8 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Count the size of the outgoing arguments.
unsigned ArgsSize = 0;
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
switch (TheCall->getArg(i).getValueType().getSimpleVT()) {
for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
switch (Outs[i].Val.getValueType().getSimpleVT()) {
default: llvm_unreachable("Unknown value type!");
case MVT::i1:
case MVT::i8:
@ -293,9 +301,7 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
// Arguments start after the 5 first operands of ISD::CALL
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
// Promote the value if needed.
switch (VA.getLocInfo()) {
@ -335,8 +341,8 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
};
unsigned ArgOffset = 68;
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
SDValue Val = TheCall->getArg(i);
for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
SDValue Val = Outs[i].Val;
MVT ObjectVT = Val.getValueType();
SDValue ValToStore(0, 0);
unsigned ObjSize;
@ -469,11 +475,10 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
CCState RVInfo(CallingConv, isVarArg, DAG.getTarget(),
CCState RVInfo(CallConv, isVarArg, DAG.getTarget(),
RVLocs, *DAG.getContext());
RVInfo.AnalyzeCallResult(TheCall, RetCC_Sparc32);
SmallVector<SDValue, 8> ResultVals;
RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@ -486,15 +491,10 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
Chain = DAG.getCopyFromReg(Chain, dl, Reg,
RVLocs[i].getValVT(), InFlag).getValue(1);
InFlag = Chain.getValue(2);
ResultVals.push_back(Chain.getValue(0));
InVals.push_back(Chain.getValue(0));
}
ResultVals.push_back(Chain);
// Merge everything together with a MERGE_VALUES node.
return DAG.getNode(ISD::MERGE_VALUES, dl,
TheCall->getVTList(), &ResultVals[0],
ResultVals.size());
return Chain;
}
@ -668,9 +668,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
// RET must be custom lowered, to meet ABI requirements
setOperationAction(ISD::RET , MVT::Other, Custom);
// VASTART needs to be custom lowered to use the VarArgsFrameIndex.
setOperationAction(ISD::VASTART , MVT::Other, Custom);
// VAARG needs to be lowered to not do unaligned accesses for doubles.
@ -948,9 +945,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::VASTART: return LowerVASTART(Op, DAG, *this);
case ISD::VAARG: return LowerVAARG(Op, DAG);
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
}
}

View File

@ -44,7 +44,6 @@ namespace llvm {
public:
SparcTargetLowering(TargetMachine &TM);
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
int getVarArgsFrameOffset() const { return VarArgsFrameOffset; }
@ -74,6 +73,29 @@ namespace llvm {
/// getFunctionAlignment - Return the Log2 alignment of this function.
virtual unsigned getFunctionAlignment(const Function *F) const;
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
};
} // end namespace llvm

View File

@ -754,8 +754,6 @@ def : Pat<(call tglobaladdr:$dst),
def : Pat<(call texternalsym:$dst),
(CALL texternalsym:$dst)>;
def : Pat<(ret), (RETL)>;
// Map integer extload's to zextloads.
def : Pat<(i32 (extloadi1 ADDRrr:$src)), (LDUBrr ADDRrr:$src)>;
def : Pat<(i32 (extloadi1 ADDRri:$src)), (LDUBri ADDRri:$src)>;

View File

@ -82,8 +82,6 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
setSchedulingPreference(SchedulingForLatency);
setBooleanContents(ZeroOrOneBooleanContent);
setOperationAction(ISD::RET, MVT::Other, Custom);
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
@ -155,9 +153,6 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) {
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::BR_CC: return LowerBR_CC(Op, DAG);
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
@ -175,27 +170,41 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
#include "SystemZGenCallingConv.inc"
SDValue SystemZTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
SelectionDAG &DAG) {
unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
switch (CC) {
SDValue
SystemZTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
switch (CallConv) {
default:
llvm_unreachable("Unsupported calling convention");
case CallingConv::C:
case CallingConv::Fast:
return LowerCCCArguments(Op, DAG);
return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals);
}
}
SDValue SystemZTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
unsigned CallingConv = TheCall->getCallingConv();
switch (CallingConv) {
SDValue
SystemZTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
switch (CallConv) {
default:
llvm_unreachable("Unsupported calling convention");
case CallingConv::Fast:
case CallingConv::C:
return LowerCCCCallTo(Op, DAG, CallingConv);
return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
Outs, Ins, dl, DAG, InVals);
}
}
@ -203,25 +212,29 @@ SDValue SystemZTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
/// generate load operations for arguments places on the stack.
// FIXME: struct return stuff
// FIXME: varargs
SDValue SystemZTargetLowering::LowerCCCArguments(SDValue Op,
SelectionDAG &DAG) {
SDValue
SystemZTargetLowering::LowerCCCArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SDValue Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
unsigned CC = MF.getFunction()->getCallingConv();
DebugLoc dl = Op.getDebugLoc();
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_SystemZ);
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CC_SystemZ);
if (isVarArg)
llvm_report_error("Varargs not supported yet");
SmallVector<SDValue, 16> ArgValues;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
SDValue ArgValue;
CCValAssign &VA = ArgLocs[i];
@ -232,7 +245,7 @@ SDValue SystemZTargetLowering::LowerCCCArguments(SDValue Op,
switch (LocVT.getSimpleVT()) {
default:
#ifndef NDEBUG
cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
cerr << "LowerFormalArguments Unhandled argument type: "
<< LocVT.getSimpleVT()
<< "\n";
#endif
@ -250,7 +263,7 @@ SDValue SystemZTargetLowering::LowerCCCArguments(SDValue Op,
unsigned VReg = RegInfo.createVirtualRegister(RC);
RegInfo.addLiveIn(VA.getLocReg(), VReg);
ArgValue = DAG.getCopyFromReg(Root, dl, VReg, LocVT);
ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, LocVT);
} else {
// Sanity check
assert(VA.isMemLoc());
@ -263,7 +276,7 @@ SDValue SystemZTargetLowering::LowerCCCArguments(SDValue Op,
// Create the SelectionDAG nodes corresponding to a load
// from this parameter
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
ArgValue = DAG.getLoad(LocVT, dl, Root, FIN,
ArgValue = DAG.getLoad(LocVT, dl, Chain, FIN,
PseudoSourceValue::getFixedStack(FI), 0);
}
@ -280,26 +293,25 @@ SDValue SystemZTargetLowering::LowerCCCArguments(SDValue Op,
if (VA.getLocInfo() != CCValAssign::Full)
ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
ArgValues.push_back(ArgValue);
InVals.push_back(ArgValue);
}
ArgValues.push_back(Root);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
/// LowerCCCCallTo - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
/// TODO: sret.
SDValue SystemZTargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
unsigned CC) {
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = Op.getDebugLoc();
SDValue
SystemZTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg>
&Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
// Offset to first argument stack slot.
@ -307,9 +319,10 @@ SDValue SystemZTargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeCallOperands(TheCall, CC_SystemZ);
CCInfo.AnalyzeCallOperands(Outs, CC_SystemZ);
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@ -325,8 +338,7 @@ SDValue SystemZTargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
// Arguments start after the 5 first operands of ISD::CALL
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
// Promote the value if needed.
switch (VA.getLocInfo()) {
@ -418,30 +430,27 @@ SDValue SystemZTargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
// Handle result values, copying them out of physregs into vregs that we
// return.
return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG),
Op.getResNo());
return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl,
DAG, InVals);
}
/// LowerCallResult - Lower the result values of an ISD::CALL into the
/// appropriate copies out of appropriate physical registers. This assumes that
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
/// being lowered. Returns a SDNode with the same number of values as the
/// ISD::CALL.
SDNode*
/// LowerCallResult - Lower the result values of a call into the
/// appropriate copies out of appropriate physical registers.
///
SDValue
SystemZTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
CallSDNode *TheCall,
unsigned CallingConv,
SelectionDAG &DAG) {
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = TheCall->getDebugLoc();
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(), RVLocs,
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs,
*DAG.getContext());
CCInfo.AnalyzeCallResult(TheCall, RetCC_SystemZ);
SmallVector<SDValue, 8> ResultVals;
CCInfo.AnalyzeCallResult(Ins, RetCC_SystemZ);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@ -465,29 +474,28 @@ SystemZTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
if (VA.getLocInfo() != CCValAssign::Full)
RetValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RetValue);
ResultVals.push_back(RetValue);
InVals.push_back(RetValue);
}
ResultVals.push_back(Chain);
// Merge everything together with a MERGE_VALUES node.
return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
&ResultVals[0], ResultVals.size()).getNode();
return Chain;
}
SDValue SystemZTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
SDValue
SystemZTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
// CCValAssign - represent the assignment of the return value to a location
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
DebugLoc dl = Op.getDebugLoc();
// CCState - Info about the registers and stack slot.
CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
// Analize return values of ISD::RET
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SystemZ);
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_SystemZ);
// If this is the first return lowered for this function, add the regs to the
// liveout set for the function.
@ -497,14 +505,12 @@ SDValue SystemZTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
// The chain is always operand #0
SDValue Chain = Op.getOperand(0);
SDValue Flag;
// Copy the result values into the output registers.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
CCValAssign &VA = RVLocs[i];
SDValue ResValue = Op.getOperand(i*2+1);
SDValue ResValue = Outs[i].Val;
assert(VA.isRegLoc() && "Can only return in registers!");
// If this is an 8/16/32-bit value, it is really should be passed promoted
@ -516,8 +522,6 @@ SDValue SystemZTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
else if (VA.getLocInfo() == CCValAssign::AExt)
ResValue = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), ResValue);
// ISD::RET => ret chain, (regnum1,val1), ...
// So i*2+1 index only the regnums
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), ResValue, Flag);
// Guarantee that all emitted copies are stuck together,

View File

@ -28,7 +28,7 @@ namespace llvm {
/// Return with a flag operand. Operand 0 is the chain operand.
RET_FLAG,
/// CALL/TAILCALL - These operations represent an abstract call
/// CALL - These operations represent an abstract call
/// instruction, which includes a bunch of information.
CALL,
@ -69,21 +69,12 @@ namespace llvm {
return 1;
}
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG);
SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC);
SDNode* LowerCallResult(SDValue Chain, SDValue InFlag,
CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG);
SDValue EmitCmp(SDValue LHS, SDValue RHS,
ISD::CondCode CC, SDValue &SystemZCC,
SelectionDAG &DAG);
@ -93,6 +84,48 @@ namespace llvm {
MachineBasicBlock *BB) const;
private:
SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue LowerCCCArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
const SystemZSubtarget &Subtarget;
const SystemZTargetMachine &TM;
const SystemZRegisterInfo *RegInfo;

View File

@ -294,8 +294,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::SELECT , MVT::i64 , Custom);
setOperationAction(ISD::SETCC , MVT::i64 , Custom);
}
// X86 ret instruction may pop stack.
setOperationAction(ISD::RET , MVT::Other, Custom);
setOperationAction(ISD::EH_RETURN , MVT::Other, Custom);
// Darwin ABI issue.
@ -1060,16 +1058,16 @@ unsigned X86TargetLowering::getFunctionAlignment(const Function *F) const {
#include "X86GenCallingConv.inc"
/// LowerRET - Lower an ISD::RET node.
SDValue X86TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
DebugLoc dl = Op.getDebugLoc();
assert((Op.getNumOperands() & 1) == 1 && "ISD::RET should have odd # args");
SDValue
X86TargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext());
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_X86);
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCInfo.AnalyzeReturn(Outs, RetCC_X86);
// If this is the first return lowered for this function, add the regs to the
// liveout set for the function.
@ -1078,37 +1076,7 @@ SDValue X86TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
if (RVLocs[i].isRegLoc())
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
SDValue Chain = Op.getOperand(0);
// Handle tail call return.
Chain = GetPossiblePreceedingTailCall(Chain, X86ISD::TAILCALL);
if (Chain.getOpcode() == X86ISD::TAILCALL) {
SDValue TailCall = Chain;
SDValue TargetAddress = TailCall.getOperand(1);
SDValue StackAdjustment = TailCall.getOperand(2);
assert(((TargetAddress.getOpcode() == ISD::Register &&
(cast<RegisterSDNode>(TargetAddress)->getReg() == X86::EAX ||
cast<RegisterSDNode>(TargetAddress)->getReg() == X86::R11)) ||
TargetAddress.getOpcode() == ISD::TargetExternalSymbol ||
TargetAddress.getOpcode() == ISD::TargetGlobalAddress) &&
"Expecting an global address, external symbol, or register");
assert(StackAdjustment.getOpcode() == ISD::Constant &&
"Expecting a const value");
SmallVector<SDValue,8> Operands;
Operands.push_back(Chain.getOperand(0));
Operands.push_back(TargetAddress);
Operands.push_back(StackAdjustment);
// Copy registers used by the call. Last operand is a flag so it is not
// copied.
for (unsigned i=3; i < TailCall.getNumOperands()-1; i++) {
Operands.push_back(Chain.getOperand(i));
}
return DAG.getNode(X86ISD::TC_RETURN, dl, MVT::Other, &Operands[0],
Operands.size());
}
// Regular return.
SDValue Flag;
SmallVector<SDValue, 6> RetOps;
@ -1120,7 +1088,7 @@ SDValue X86TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
for (unsigned i = 0; i != RVLocs.size(); ++i) {
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
SDValue ValToCopy = Op.getOperand(i*2+1);
SDValue ValToCopy = Outs[i].Val;
// Returns in ST0/ST1 are handled specially: these are pushed as operands to
// the RET instruction and handled by the FP Stackifier.
@ -1179,26 +1147,22 @@ SDValue X86TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
MVT::Other, &RetOps[0], RetOps.size());
}
/// LowerCallResult - Lower the result values of a call into the
/// appropriate copies out of appropriate physical registers.
///
SDValue
X86TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
/// LowerCallResult - Lower the result values of an ISD::CALL into the
/// appropriate copies out of appropriate physical registers. This assumes that
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
/// being lowered. The returns a SDNode with the same number of values as the
/// ISD::CALL.
SDNode *X86TargetLowering::
LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG) {
DebugLoc dl = TheCall->getDebugLoc();
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
bool isVarArg = TheCall->isVarArg();
bool Is64Bit = Subtarget->is64Bit();
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(),
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCInfo.AnalyzeCallResult(TheCall, RetCC_X86);
SmallVector<SDValue, 8> ResultVals;
CCInfo.AnalyzeCallResult(Ins, RetCC_X86);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@ -1207,7 +1171,7 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
// If this is x86-64, and we disabled SSE, we can't return FP values
if ((CopyVT == MVT::f32 || CopyVT == MVT::f64) &&
((Is64Bit || TheCall->isInreg()) && !Subtarget->hasSSE1())) {
((Is64Bit || Ins[i].Flags.isInReg()) && !Subtarget->hasSSE1())) {
llvm_report_error("SSE register return with SSE disabled");
}
@ -1250,13 +1214,10 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
DAG.getIntPtrConstant(1));
}
ResultVals.push_back(Val);
InVals.push_back(Val);
}
// Merge everything together with a MERGE_VALUES node.
ResultVals.push_back(Chain);
return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
&ResultVals[0], ResultVals.size()).getNode();
return Chain;
}
@ -1270,24 +1231,23 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
// For info on fast calling convention see Fast Calling Convention (tail call)
// implementation LowerX86_32FastCCCallTo.
/// CallIsStructReturn - Determines whether a CALL node uses struct return
/// CallIsStructReturn - Determines whether a call uses struct return
/// semantics.
static bool CallIsStructReturn(CallSDNode *TheCall) {
unsigned NumOps = TheCall->getNumArgs();
if (!NumOps)
static bool CallIsStructReturn(const SmallVectorImpl<ISD::OutputArg> &Outs) {
if (Outs.empty())
return false;
return TheCall->getArgFlags(0).isSRet();
return Outs[0].Flags.isSRet();
}
/// ArgsAreStructReturn - Determines whether a function uses struct
/// return semantics.
static bool ArgsAreStructReturn(SDValue Op) {
unsigned NumArgs = Op.getNode()->getNumValues() - 1;
if (!NumArgs)
static bool
ArgsAreStructReturn(const SmallVectorImpl<ISD::InputArg> &Ins) {
if (Ins.empty())
return false;
return cast<ARG_FLAGSSDNode>(Op.getOperand(3))->getArgFlags().isSRet();
return Ins[0].Flags.isSRet();
}
/// IsCalleePop - Determines whether the callee is required to pop its
@ -1326,14 +1286,13 @@ CCAssignFn *X86TargetLowering::CCAssignFnForNode(unsigned CC) const {
return CC_X86_32_C;
}
/// NameDecorationForFORMAL_ARGUMENTS - Selects the appropriate decoration to
/// apply to a MachineFunction containing a given FORMAL_ARGUMENTS node.
/// NameDecorationForCallConv - Selects the appropriate decoration to
/// apply to a MachineFunction containing a given calling convention.
NameDecorationStyle
X86TargetLowering::NameDecorationForFORMAL_ARGUMENTS(SDValue Op) {
unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
if (CC == CallingConv::X86_FastCall)
X86TargetLowering::NameDecorationForCallConv(unsigned CallConv) {
if (CallConv == CallingConv::X86_FastCall)
return FastCall;
else if (CC == CallingConv::X86_StdCall)
else if (CallConv == CallingConv::X86_StdCall)
return StdCall;
return None;
}
@ -1352,15 +1311,18 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
/*AlwaysInline=*/true, NULL, 0, NULL, 0);
}
SDValue X86TargetLowering::LowerMemArgument(SDValue Op, SelectionDAG &DAG,
const CCValAssign &VA,
MachineFrameInfo *MFI,
unsigned CC,
SDValue Root, unsigned i) {
SDValue
X86TargetLowering::LowerMemArgument(SDValue Chain,
unsigned CallConv,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
const CCValAssign &VA,
MachineFrameInfo *MFI,
unsigned i) {
// Create the nodes corresponding to a load from this parameter slot.
ISD::ArgFlagsTy Flags =
cast<ARG_FLAGSSDNode>(Op.getOperand(3 + i))->getArgFlags();
bool AlwaysUseMutable = (CC==CallingConv::Fast) && PerformTailCallOpt;
ISD::ArgFlagsTy Flags = Ins[i].Flags;
bool AlwaysUseMutable = (CallConv==CallingConv::Fast) && PerformTailCallOpt;
bool isImmutable = !AlwaysUseMutable && !Flags.isByVal();
// FIXME: For now, all byval parameter objects are marked mutable. This can be
@ -1372,15 +1334,21 @@ SDValue X86TargetLowering::LowerMemArgument(SDValue Op, SelectionDAG &DAG,
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
if (Flags.isByVal())
return FIN;
return DAG.getLoad(VA.getValVT(), Op.getDebugLoc(), Root, FIN,
return DAG.getLoad(VA.getValVT(), dl, Chain, FIN,
PseudoSourceValue::getFixedStack(FI), 0);
}
SDValue
X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
X86TargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
DebugLoc dl = Op.getDebugLoc();
const Function* Fn = MF.getFunction();
if (Fn->hasExternalLinkage() &&
@ -1389,24 +1357,21 @@ X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
FuncInfo->setForceFramePointer(true);
// Decorate the function name.
FuncInfo->setDecorationStyle(NameDecorationForFORMAL_ARGUMENTS(Op));
FuncInfo->setDecorationStyle(NameDecorationForCallConv(CallConv));
MachineFrameInfo *MFI = MF.getFrameInfo();
SDValue Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
unsigned CC = MF.getFunction()->getCallingConv();
bool Is64Bit = Subtarget->is64Bit();
bool IsWin64 = Subtarget->isTargetWin64();
assert(!(isVarArg && CC == CallingConv::Fast) &&
assert(!(isVarArg && CallConv == CallingConv::Fast) &&
"Var args not supported with calling convention fastcc");
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Op.getNode(), CCAssignFnForNode(CC));
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForNode(CallConv));
SmallVector<SDValue, 8> ArgValues;
unsigned LastVal = ~0U;
SDValue ArgValue;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
@ -1436,7 +1401,7 @@ X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
llvm_unreachable("Unknown argument type!");
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
ArgValue = DAG.getCopyFromReg(Root, dl, Reg, RegVT);
ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it is really passed promoted to 32
// bits. Insert an assert[sz]ext to capture this, then truncate to the
@ -1461,14 +1426,14 @@ X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
}
} else {
assert(VA.isMemLoc());
ArgValue = LowerMemArgument(Op, DAG, VA, MFI, CC, Root, i);
ArgValue = LowerMemArgument(Chain, CallConv, Ins, dl, DAG, VA, MFI, i);
}
// If value is passed via pointer - do a load.
if (VA.getLocInfo() == CCValAssign::Indirect)
ArgValue = DAG.getLoad(VA.getValVT(), dl, Root, ArgValue, NULL, 0);
ArgValue = DAG.getLoad(VA.getValVT(), dl, Chain, ArgValue, NULL, 0);
ArgValues.push_back(ArgValue);
InVals.push_back(ArgValue);
}
// The x86-64 ABI for returning structs by value requires that we copy
@ -1481,19 +1446,19 @@ X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
FuncInfo->setSRetReturnReg(Reg);
}
SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, ArgValues[0]);
Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Root);
SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]);
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
}
unsigned StackSize = CCInfo.getNextStackOffset();
// align stack specially for tail calls
if (PerformTailCallOpt && CC == CallingConv::Fast)
if (PerformTailCallOpt && CallConv == CallingConv::Fast)
StackSize = GetAlignedArgumentStackSize(StackSize, DAG);
// If the function takes variable number of arguments, make a frame index for
// the start of the first vararg value... for expansion of llvm.va_start.
if (isVarArg) {
if (Is64Bit || CC != CallingConv::X86_FastCall) {
if (Is64Bit || CallConv != CallingConv::X86_FastCall) {
VarArgsFrameIndex = MFI->CreateFixedObject(1, StackSize);
}
if (Is64Bit) {
@ -1555,7 +1520,7 @@ X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
for (; NumIntRegs != TotalNumIntRegs; ++NumIntRegs) {
unsigned VReg = MF.addLiveIn(GPR64ArgRegs[NumIntRegs],
X86::GR64RegisterClass);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::i64);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64);
SDValue Store =
DAG.getStore(Val.getValue(1), dl, Val, FIN,
PseudoSourceValue::getFixedStack(RegSaveFrameIndex), 0);
@ -1570,7 +1535,7 @@ X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
for (; NumXMMRegs != TotalNumXMMRegs; ++NumXMMRegs) {
unsigned VReg = MF.addLiveIn(XMMArgRegs[NumXMMRegs],
X86::VR128RegisterClass);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::v4f32);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::v4f32);
SDValue Store =
DAG.getStore(Val.getValue(1), dl, Val, FIN,
PseudoSourceValue::getFixedStack(RegSaveFrameIndex), 0);
@ -1579,46 +1544,41 @@ X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
DAG.getIntPtrConstant(16));
}
if (!MemOps.empty())
Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOps[0], MemOps.size());
}
}
ArgValues.push_back(Root);
// Some CCs need callee pop.
if (IsCalleePop(isVarArg, CC)) {
if (IsCalleePop(isVarArg, CallConv)) {
BytesToPopOnReturn = StackSize; // Callee pops everything.
BytesCallerReserves = 0;
} else {
BytesToPopOnReturn = 0; // Callee pops nothing.
// If this is an sret function, the return should pop the hidden pointer.
if (!Is64Bit && CC != CallingConv::Fast && ArgsAreStructReturn(Op))
if (!Is64Bit && CallConv != CallingConv::Fast && ArgsAreStructReturn(Ins))
BytesToPopOnReturn = 4;
BytesCallerReserves = StackSize;
}
if (!Is64Bit) {
RegSaveFrameIndex = 0xAAAAAAA; // RegSaveFrameIndex is X86-64 only.
if (CC == CallingConv::X86_FastCall)
if (CallConv == CallingConv::X86_FastCall)
VarArgsFrameIndex = 0xAAAAAAA; // fastcc functions can't have varargs.
}
FuncInfo->setBytesToPopOnReturn(BytesToPopOnReturn);
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
return Chain;
}
SDValue
X86TargetLowering::LowerMemOpCallTo(CallSDNode *TheCall, SelectionDAG &DAG,
const SDValue &StackPtr,
X86TargetLowering::LowerMemOpCallTo(SDValue Chain,
SDValue StackPtr, SDValue Arg,
DebugLoc dl, SelectionDAG &DAG,
const CCValAssign &VA,
SDValue Chain,
SDValue Arg, ISD::ArgFlagsTy Flags) {
ISD::ArgFlagsTy Flags) {
const unsigned FirstStackArgOffset = (Subtarget->isTargetWin64() ? 32 : 0);
DebugLoc dl = TheCall->getDebugLoc();
unsigned LocMemOffset = FirstStackArgOffset + VA.getLocMemOffset();
SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset);
PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff);
@ -1669,34 +1629,37 @@ EmitTailCallStoreRetAddr(SelectionDAG & DAG, MachineFunction &MF,
return Chain;
}
SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
MachineFunction &MF = DAG.getMachineFunction();
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
unsigned CC = TheCall->getCallingConv();
bool isVarArg = TheCall->isVarArg();
bool IsTailCall = TheCall->isTailCall() &&
CC == CallingConv::Fast && PerformTailCallOpt;
SDValue Callee = TheCall->getCallee();
bool Is64Bit = Subtarget->is64Bit();
bool IsStructRet = CallIsStructReturn(TheCall);
DebugLoc dl = TheCall->getDebugLoc();
SDValue
X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
assert(!(isVarArg && CC == CallingConv::Fast) &&
MachineFunction &MF = DAG.getMachineFunction();
bool Is64Bit = Subtarget->is64Bit();
bool IsStructRet = CallIsStructReturn(Outs);
assert((!isTailCall ||
(CallConv == CallingConv::Fast && PerformTailCallOpt)) &&
"IsEligibleForTailCallOptimization missed a case!");
assert(!(isVarArg && CallConv == CallingConv::Fast) &&
"Var args not supported with calling convention fastcc");
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeCallOperands(TheCall, CCAssignFnForNode(CC));
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForNode(CallConv));
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
if (PerformTailCallOpt && CC == CallingConv::Fast)
if (PerformTailCallOpt && CallConv == CallingConv::Fast)
NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG);
int FPDiff = 0;
if (IsTailCall) {
if (isTailCall) {
// Lower arguments at fp - stackoffset + fpdiff.
unsigned NumBytesCallerPushed =
MF.getInfo<X86MachineFunctionInfo>()->getBytesToPopOnReturn();
@ -1712,7 +1675,7 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
SDValue RetAddrFrIdx;
// Load return adress for tail calls.
Chain = EmitTailCallLoadRetAddr(DAG, RetAddrFrIdx, Chain, IsTailCall, Is64Bit,
Chain = EmitTailCallLoadRetAddr(DAG, RetAddrFrIdx, Chain, isTailCall, Is64Bit,
FPDiff, dl);
SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
@ -1724,8 +1687,8 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
MVT RegVT = VA.getLocVT();
SDValue Arg = TheCall->getArg(i);
ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i);
SDValue Arg = Outs[i].Val;
ISD::ArgFlagsTy Flags = Outs[i].Flags;
bool isByVal = Flags.isByVal();
// Promote the value if needed.
@ -1764,13 +1727,13 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
if (VA.isRegLoc()) {
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
} else {
if (!IsTailCall || (IsTailCall && isByVal)) {
if (!isTailCall || (isTailCall && isByVal)) {
assert(VA.isMemLoc());
if (StackPtr.getNode() == 0)
StackPtr = DAG.getCopyFromReg(Chain, dl, X86StackPtr, getPointerTy());
MemOpChains.push_back(LowerMemOpCallTo(TheCall, DAG, StackPtr, VA,
Chain, Arg, Flags));
MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg,
dl, DAG, VA, Flags));
}
}
}
@ -1784,7 +1747,7 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
SDValue InFlag;
// Tail call byval lowering might overwrite argument registers so in case of
// tail call optimization the copies to registers are lowered later.
if (!IsTailCall)
if (!isTailCall)
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
RegsToPass[i].second, InFlag);
@ -1795,7 +1758,7 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
if (Subtarget->isPICStyleGOT()) {
// ELF / PIC requires GOT in the EBX register before function calls via PLT
// GOT pointer.
if (!IsTailCall) {
if (!isTailCall) {
Chain = DAG.getCopyToReg(Chain, dl, X86::EBX,
DAG.getNode(X86ISD::GlobalBaseReg,
DebugLoc::getUnknownLoc(),
@ -1847,7 +1810,15 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// For tail calls lower the arguments to the 'real' stack slot.
if (IsTailCall) {
if (isTailCall) {
// Force all the incoming stack arguments to be loaded from the stack
// before any new outgoing arguments are stored to the stack, because the
// outgoing stack slots may alias the incoming argument stack slots, and
// the alias isn't otherwise explicit. This is slightly more conservative
// than necessary, because it means that each store effectively depends
// on every argument instead of just those arguments it would clobber.
SDValue ArgChain = DAG.getStackArgumentTokenFactor(Chain);
SmallVector<SDValue, 8> MemOpChains2;
SDValue FIN;
int FI = 0;
@ -1857,8 +1828,8 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
CCValAssign &VA = ArgLocs[i];
if (!VA.isRegLoc()) {
assert(VA.isMemLoc());
SDValue Arg = TheCall->getArg(i);
ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i);
SDValue Arg = Outs[i].Val;
ISD::ArgFlagsTy Flags = Outs[i].Flags;
// Create frame index.
int32_t Offset = VA.getLocMemOffset()+FPDiff;
uint32_t OpSize = (VA.getLocVT().getSizeInBits()+7)/8;
@ -1873,12 +1844,13 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
getPointerTy());
Source = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, Source);
MemOpChains2.push_back(CreateCopyOfByValArgument(Source, FIN, Chain,
MemOpChains2.push_back(CreateCopyOfByValArgument(Source, FIN,
ArgChain,
Flags, DAG, dl));
} else {
// Store relative to framepointer.
MemOpChains2.push_back(
DAG.getStore(Chain, dl, Arg, FIN,
DAG.getStore(ArgChain, dl, Arg, FIN,
PseudoSourceValue::getFixedStack(FI), 0));
}
}
@ -1948,7 +1920,7 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(),
OpFlags);
} else if (IsTailCall) {
} else if (isTailCall) {
unsigned Opc = Is64Bit ? X86::R11 : X86::EAX;
Chain = DAG.getCopyToReg(Chain, dl,
@ -1963,20 +1935,16 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
SmallVector<SDValue, 8> Ops;
if (IsTailCall) {
if (isTailCall) {
Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
DAG.getIntPtrConstant(0, true), InFlag);
InFlag = Chain.getValue(1);
// Returns a chain & a flag for retval copy to use.
NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
Ops.clear();
}
Ops.push_back(Chain);
Ops.push_back(Callee);
if (IsTailCall)
if (isTailCall)
Ops.push_back(DAG.getConstant(FPDiff, MVT::i32));
// Add argument registers to the end of the list so that they are known live
@ -1986,7 +1954,7 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
RegsToPass[i].second.getValueType()));
// Add an implicit use GOT pointer in EBX.
if (!IsTailCall && Subtarget->isPICStyleGOT())
if (!isTailCall && Subtarget->isPICStyleGOT())
Ops.push_back(DAG.getRegister(X86::EBX, getPointerTy()));
// Add an implicit use of AL for x86 vararg functions.
@ -1996,13 +1964,28 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
if (InFlag.getNode())
Ops.push_back(InFlag);
if (IsTailCall) {
assert(InFlag.getNode() &&
"Flag must be set. Depend on flag being set in LowerRET");
Chain = DAG.getNode(X86ISD::TAILCALL, dl,
TheCall->getVTList(), &Ops[0], Ops.size());
if (isTailCall) {
// If this is the first return lowered for this function, add the regs
// to the liveout set for the function.
if (MF.getRegInfo().liveout_empty()) {
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs,
*DAG.getContext());
CCInfo.AnalyzeCallResult(Ins, RetCC_X86);
for (unsigned i = 0; i != RVLocs.size(); ++i)
if (RVLocs[i].isRegLoc())
MF.getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
return SDValue(Chain.getNode(), Op.getResNo());
assert(((Callee.getOpcode() == ISD::Register &&
(cast<RegisterSDNode>(Callee)->getReg() == X86::EAX ||
cast<RegisterSDNode>(Callee)->getReg() == X86::R9)) ||
Callee.getOpcode() == ISD::TargetExternalSymbol ||
Callee.getOpcode() == ISD::TargetGlobalAddress) &&
"Expecting an global address, external symbol, or register");
return DAG.getNode(X86ISD::TC_RETURN, dl,
NodeTys, &Ops[0], Ops.size());
}
Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
@ -2010,9 +1993,9 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Create the CALLSEQ_END node.
unsigned NumBytesForCalleeToPush;
if (IsCalleePop(isVarArg, CC))
if (IsCalleePop(isVarArg, CallConv))
NumBytesForCalleeToPush = NumBytes; // Callee pops everything
else if (!Is64Bit && CC != CallingConv::Fast && IsStructRet)
else if (!Is64Bit && CallConv != CallingConv::Fast && IsStructRet)
// If this is is a call to a struct-return function, the callee
// pops the hidden struct pointer, so we have to push it back.
// This is common for Darwin/X86, Linux & Mingw32 targets.
@ -2030,8 +2013,8 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Handle result values, copying them out of physregs into vregs that we
// return.
return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG),
Op.getResNo());
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
Ins, dl, DAG, InVals);
}
@ -2088,25 +2071,18 @@ unsigned X86TargetLowering::GetAlignedArgumentStackSize(unsigned StackSize,
return Offset;
}
/// IsEligibleForTailCallElimination - Check to see whether the next instruction
/// following the call is a return. A function is eligible if caller/callee
/// calling conventions match, currently only fastcc supports tail calls, and
/// the function CALL is immediatly followed by a RET.
bool X86TargetLowering::IsEligibleForTailCallOptimization(CallSDNode *TheCall,
SDValue Ret,
SelectionDAG& DAG) const {
if (!PerformTailCallOpt)
return false;
if (CheckTailCallReturnConstraints(TheCall, Ret)) {
unsigned CallerCC =
DAG.getMachineFunction().getFunction()->getCallingConv();
unsigned CalleeCC = TheCall->getCallingConv();
if (CalleeCC == CallingConv::Fast && CallerCC == CalleeCC)
return true;
}
return false;
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
/// for tail call optimization. Targets which want to do tail call
/// optimization should implement this function.
bool
X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
unsigned CalleeCC,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SelectionDAG& DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
unsigned CallerCC = MF.getFunction()->getCallingConv();
return CalleeCC == CallingConv::Fast && CallerCC == CalleeCC;
}
FastISel *
@ -5825,7 +5801,7 @@ X86TargetLowering::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
Args.push_back(Entry);
std::pair<SDValue,SDValue> CallResult =
LowerCallTo(Chain, Type::VoidTy, false, false, false, false,
0, CallingConv::C, false,
0, CallingConv::C, false, /*isReturnValueUsed=*/false,
DAG.getExternalSymbol(bzeroEntry, IntPtr), Args, DAG, dl);
return CallResult.second;
}
@ -6845,9 +6821,6 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::SELECT: return LowerSELECT(Op, DAG);
case ISD::BRCOND: return LowerBRCOND(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::VASTART: return LowerVASTART(Op, DAG);
case ISD::VAARG: return LowerVAARG(Op, DAG);
case ISD::VACOPY: return LowerVACOPY(Op, DAG);
@ -7009,7 +6982,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::FLD: return "X86ISD::FLD";
case X86ISD::FST: return "X86ISD::FST";
case X86ISD::CALL: return "X86ISD::CALL";
case X86ISD::TAILCALL: return "X86ISD::TAILCALL";
case X86ISD::RDTSC_DAG: return "X86ISD::RDTSC_DAG";
case X86ISD::BT: return "X86ISD::BT";
case X86ISD::CMP: return "X86ISD::CMP";

View File

@ -85,7 +85,7 @@ namespace llvm {
/// as.
FST,
/// CALL/TAILCALL - These operations represent an abstract X86 call
/// CALL - These operations represent an abstract X86 call
/// instruction, which includes a bunch of information. In particular the
/// operands of these node are:
///
@ -102,12 +102,8 @@ namespace llvm {
/// #1 - The first register result value (optional)
/// #2 - The second register result value (optional)
///
/// The CALL vs TAILCALL distinction boils down to whether the callee is
/// known not to modify the caller's stack frame, as is standard with
/// LLVM.
CALL,
TAILCALL,
/// RDTSC_DAG - This operation implements the lowering for
/// readcyclecounter
RDTSC_DAG,
@ -508,9 +504,12 @@ namespace llvm {
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
/// for tail call optimization. Targets which want to do tail call
/// optimization should implement this function.
virtual bool IsEligibleForTailCallOptimization(CallSDNode *TheCall,
SDValue Ret,
SelectionDAG &DAG) const;
virtual bool
IsEligibleForTailCallOptimization(SDValue Callee,
unsigned CalleeCC,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SelectionDAG& DAG) const;
virtual const X86Subtarget* getSubtarget() {
return Subtarget;
@ -563,26 +562,30 @@ namespace llvm {
bool X86ScalarSSEf32;
bool X86ScalarSSEf64;
SDNode *LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG);
SDValue LowerMemArgument(SDValue Op, SelectionDAG &DAG,
const CCValAssign &VA, MachineFrameInfo *MFI,
unsigned CC, SDValue Root, unsigned i);
SDValue LowerMemOpCallTo(CallSDNode *TheCall, SelectionDAG &DAG,
const SDValue &StackPtr,
const CCValAssign &VA, SDValue Chain,
SDValue Arg, ISD::ArgFlagsTy Flags);
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue LowerMemArgument(SDValue Chain,
unsigned CallConv,
const SmallVectorImpl<ISD::InputArg> &ArgInfo,
DebugLoc dl, SelectionDAG &DAG,
const CCValAssign &VA, MachineFrameInfo *MFI,
unsigned i);
SDValue LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, SDValue Arg,
DebugLoc dl, SelectionDAG &DAG,
const CCValAssign &VA,
ISD::ArgFlagsTy Flags);
// Call lowering helpers.
bool IsCalleePop(bool isVarArg, unsigned CallingConv);
bool IsCalleePop(bool isVarArg, unsigned CallConv);
SDValue EmitTailCallLoadRetAddr(SelectionDAG &DAG, SDValue &OutRetAddr,
SDValue Chain, bool IsTailCall, bool Is64Bit,
int FPDiff, DebugLoc dl);
CCAssignFn *CCAssignFnForNode(unsigned CallingConv) const;
NameDecorationStyle NameDecorationForFORMAL_ARGUMENTS(SDValue Op);
CCAssignFn *CCAssignFnForNode(unsigned CallConv) const;
NameDecorationStyle NameDecorationForCallConv(unsigned CallConv);
unsigned GetAlignedArgumentStackSize(unsigned StackSize, SelectionDAG &DAG);
std::pair<SDValue,SDValue> FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG,
@ -619,10 +622,7 @@ namespace llvm {
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG);
SDValue LowerMEMSET(SDValue Op, SelectionDAG &DAG);
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG);
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG);
SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG);
@ -642,6 +642,26 @@ namespace llvm {
SDValue LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG);
SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG);
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg, bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
void ReplaceATOMIC_BINARY_64(SDNode *N, SmallVectorImpl<SDValue> &Results,
SelectionDAG &DAG, unsigned NewOp);

View File

@ -1528,23 +1528,7 @@ def : Pat<(X86call (i64 tglobaladdr:$dst)),
def : Pat<(X86call (i64 texternalsym:$dst)),
(WINCALL64pcrel32 texternalsym:$dst)>, Requires<[IsWin64]>;
def : Pat<(X86tailcall (i64 tglobaladdr:$dst)),
(CALL64pcrel32 tglobaladdr:$dst)>;
def : Pat<(X86tailcall (i64 texternalsym:$dst)),
(CALL64pcrel32 texternalsym:$dst)>;
def : Pat<(X86tailcall GR64:$dst),
(CALL64r GR64:$dst)>;
// tailcall stuff
def : Pat<(X86tailcall GR32:$dst),
(TAILCALL)>;
def : Pat<(X86tailcall (i64 tglobaladdr:$dst)),
(TAILCALL)>;
def : Pat<(X86tailcall (i64 texternalsym:$dst)),
(TAILCALL)>;
def : Pat<(X86tcret GR64:$dst, imm:$off),
(TCRETURNri64 GR64:$dst, imm:$off)>;

View File

@ -124,9 +124,6 @@ def X86callseq_end :
def X86call : SDNode<"X86ISD::CALL", SDT_X86Call,
[SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
def X86tailcall: SDNode<"X86ISD::TAILCALL", SDT_X86Call,
[SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr,
[SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore]>;
def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr,
@ -622,10 +619,6 @@ let isCall = 1 in
// Tail call stuff.
def TAILCALL : I<0, Pseudo, (outs), (ins),
"#TAILCALL",
[]>;
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
def TCRETURNdi : I<0, Pseudo, (outs), (ins i32imm:$dst, i32imm:$offset, variable_ops),
"#TC_RETURN $dst $offset",
@ -3452,14 +3445,6 @@ def : Pat<(store (i32 (X86Wrapper texternalsym:$src)), addr:$dst),
// Calls
// tailcall stuff
def : Pat<(X86tailcall GR32:$dst),
(TAILCALL)>;
def : Pat<(X86tailcall (i32 tglobaladdr:$dst)),
(TAILCALL)>;
def : Pat<(X86tailcall (i32 texternalsym:$dst)),
(TAILCALL)>;
def : Pat<(X86tcret GR32:$dst, imm:$off),
(TCRETURNri GR32:$dst, imm:$off)>;

View File

@ -113,9 +113,6 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
// RET must be custom lowered, to meet ABI requirements
setOperationAction(ISD::RET, MVT::Other, Custom);
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
// Thread Local Storage
@ -162,9 +159,6 @@ SDValue XCoreTargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) {
switch (Op.getOpcode())
{
case ISD::CALL: return LowerCALL(Op, DAG);
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
@ -455,6 +449,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG)
std::pair<SDValue, SDValue> CallResult =
LowerCallTo(Chain, IntPtrTy, false, false,
false, false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
DAG.getExternalSymbol("__misaligned_load", getPointerTy()),
Args, DAG, dl);
@ -515,6 +510,7 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG)
std::pair<SDValue, SDValue> CallResult =
LowerCallTo(Chain, Type::VoidTy, false, false,
false, false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
DAG.getExternalSymbol("__misaligned_store", getPointerTy()),
Args, DAG, dl);
@ -603,35 +599,33 @@ SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//
// The lower operations present on calling convention works on this order:
// LowerCALL (virt regs --> phys regs, virt regs --> stack)
// LowerFORMAL_ARGUMENTS (phys --> virt regs, stack --> virt regs)
// LowerRET (virt regs --> phys regs)
// LowerCALL (phys regs --> virt regs)
//
//===----------------------------------------------------------------------===//
#include "XCoreGenCallingConv.inc"
//===----------------------------------------------------------------------===//
// CALL Calling Convention Implementation
// Call Calling Convention Implementation
//===----------------------------------------------------------------------===//
/// XCore custom CALL implementation
SDValue XCoreTargetLowering::
LowerCALL(SDValue Op, SelectionDAG &DAG)
{
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
unsigned CallingConv = TheCall->getCallingConv();
/// XCore call implementation
SDValue
XCoreTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// For now, only CallingConv::C implemented
switch (CallingConv)
switch (CallConv)
{
default:
llvm_unreachable("Unsupported calling convention");
case CallingConv::Fast:
case CallingConv::C:
return LowerCCCCallTo(Op, DAG, CallingConv);
return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
Outs, Ins, dl, DAG, InVals);
}
}
@ -639,24 +633,25 @@ LowerCALL(SDValue Op, SelectionDAG &DAG)
/// regs to (physical regs)/(stack frame), CALLSEQ_START and
/// CALLSEQ_END are emitted.
/// TODO: isTailCall, sret.
SDValue XCoreTargetLowering::
LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC)
{
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
SDValue Chain = TheCall->getChain();
SDValue Callee = TheCall->getCallee();
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = Op.getDebugLoc();
SDValue
XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
// The ABI dictates there should be one stack slot available to the callee
// on function entry (for saving lr).
CCInfo.AllocateStack(4, 4);
CCInfo.AnalyzeCallOperands(TheCall, CC_XCore);
CCInfo.AnalyzeCallOperands(Outs, CC_XCore);
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@ -670,9 +665,7 @@ LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC)
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
// Arguments start after the 5 first operands of ISD::CALL
SDValue Arg = TheCall->getArg(i);
SDValue Arg = Outs[i].Val;
// Promote the value if needed.
switch (VA.getLocInfo()) {
@ -759,60 +752,58 @@ LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC)
// Handle result values, copying them out of physregs into vregs that we
// return.
return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG),
Op.getResNo());
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
Ins, dl, DAG, InVals);
}
/// LowerCallResult - Lower the result values of an ISD::CALL into the
/// appropriate copies out of appropriate physical registers. This assumes that
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
/// being lowered. Returns a SDNode with the same number of values as the
/// ISD::CALL.
SDNode *XCoreTargetLowering::
LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG) {
bool isVarArg = TheCall->isVarArg();
DebugLoc dl = TheCall->getDebugLoc();
/// LowerCallResult - Lower the result values of a call into the
/// appropriate copies out of appropriate physical registers.
SDValue
XCoreTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(),
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
CCInfo.AnalyzeCallResult(TheCall, RetCC_XCore);
SmallVector<SDValue, 8> ResultVals;
CCInfo.AnalyzeCallResult(Ins, RetCC_XCore);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
RVLocs[i].getValVT(), InFlag).getValue(1);
InFlag = Chain.getValue(2);
ResultVals.push_back(Chain.getValue(0));
InVals.push_back(Chain.getValue(0));
}
ResultVals.push_back(Chain);
// Merge everything together with a MERGE_VALUES node.
return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
&ResultVals[0], ResultVals.size()).getNode();
return Chain;
}
//===----------------------------------------------------------------------===//
// FORMAL_ARGUMENTS Calling Convention Implementation
// Formal Arguments Calling Convention Implementation
//===----------------------------------------------------------------------===//
/// XCore custom FORMAL_ARGUMENTS implementation
SDValue XCoreTargetLowering::
LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
{
unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
switch(CC)
/// XCore formal arguments implementation
SDValue
XCoreTargetLowering::LowerFormalArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
switch (CallConv)
{
default:
llvm_unreachable("Unsupported calling convention");
case CallingConv::C:
case CallingConv::Fast:
return LowerCCCArguments(Op, DAG);
return LowerCCCArguments(Chain, CallConv, isVarArg,
Ins, dl, DAG, InVals);
}
}
@ -820,27 +811,28 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
/// virtual registers and generate load operations for
/// arguments places on the stack.
/// TODO: sret
SDValue XCoreTargetLowering::
LowerCCCArguments(SDValue Op, SelectionDAG &DAG)
{
SDValue
XCoreTargetLowering::LowerCCCArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg>
&Ins,
DebugLoc dl,
SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SDValue Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
unsigned CC = MF.getFunction()->getCallingConv();
DebugLoc dl = Op.getDebugLoc();
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_XCore);
CCInfo.AnalyzeFormalArguments(Ins, CC_XCore);
unsigned StackSlotSize = XCoreFrameInfo::stackSlotSize();
SmallVector<SDValue, 16> ArgValues;
unsigned LRSaveSize = StackSlotSize;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
@ -854,7 +846,7 @@ LowerCCCArguments(SDValue Op, SelectionDAG &DAG)
default:
{
#ifndef NDEBUG
errs() << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
errs() << "LowerFormalArguments Unhandled argument type: "
<< RegVT.getSimpleVT() << "\n";
#endif
llvm_unreachable(0);
@ -863,7 +855,7 @@ LowerCCCArguments(SDValue Op, SelectionDAG &DAG)
unsigned VReg = RegInfo.createVirtualRegister(
XCore::GRRegsRegisterClass);
RegInfo.addLiveIn(VA.getLocReg(), VReg);
ArgValues.push_back(DAG.getCopyFromReg(Root, dl, VReg, RegVT));
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
}
} else {
// sanity check
@ -871,7 +863,7 @@ LowerCCCArguments(SDValue Op, SelectionDAG &DAG)
// Load the argument to a virtual register
unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
if (ObjSize > StackSlotSize) {
errs() << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
errs() << "LowerFormalArguments Unhandled argument type: "
<< VA.getLocVT().getSimpleVT()
<< "\n";
}
@ -882,7 +874,7 @@ LowerCCCArguments(SDValue Op, SelectionDAG &DAG)
// Create the SelectionDAG nodes corresponding to a load
//from this parameter
SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
ArgValues.push_back(DAG.getLoad(VA.getLocVT(), dl, Root, FIN, NULL, 0));
InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, NULL, 0));
}
}
@ -911,14 +903,14 @@ LowerCCCArguments(SDValue Op, SelectionDAG &DAG)
unsigned VReg = RegInfo.createVirtualRegister(
XCore::GRRegsRegisterClass);
RegInfo.addLiveIn(ArgRegs[i], VReg);
SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
// Move argument from virt reg -> stack
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0);
MemOps.push_back(Store);
}
if (!MemOps.empty())
Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOps[0], MemOps.size());
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOps[0], MemOps.size());
} else {
// This will point to the next argument passed via stack.
XFI->setVarArgsFrameIndex(
@ -926,34 +918,29 @@ LowerCCCArguments(SDValue Op, SelectionDAG &DAG)
}
}
ArgValues.push_back(Root);
// Return the new list of results.
std::vector<MVT> RetVT(Op.getNode()->value_begin(),
Op.getNode()->value_end());
return DAG.getNode(ISD::MERGE_VALUES, dl, RetVT,
&ArgValues[0], ArgValues.size());
return Chain;
}
//===----------------------------------------------------------------------===//
// Return Value Calling Convention Implementation
//===----------------------------------------------------------------------===//
SDValue XCoreTargetLowering::
LowerRET(SDValue Op, SelectionDAG &DAG)
{
SDValue
XCoreTargetLowering::LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG) {
// CCValAssign - represent the assignment of
// the return value to a location
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
DebugLoc dl = Op.getDebugLoc();
// CCState - Info about the registers and stack slot.
CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
RVLocs, *DAG.getContext());
// Analize return values of ISD::RET
CCInfo.AnalyzeReturn(Op.getNode(), RetCC_XCore);
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_XCore);
// If this is the first return lowered for this function, add
// the regs to the liveout set for the function.
@ -963,8 +950,6 @@ LowerRET(SDValue Op, SelectionDAG &DAG)
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
// The chain is always operand #0
SDValue Chain = Op.getOperand(0);
SDValue Flag;
// Copy the result values into the output registers.
@ -972,10 +957,8 @@ LowerRET(SDValue Op, SelectionDAG &DAG)
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
// ISD::RET => ret chain, (regnum1,val1), ...
// So i*2+1 index only the regnums
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Op.getOperand(i*2+1), Flag);
Outs[i].Val, Flag);
// guarantee that all emitted copies are
// stuck together, avoiding something bad

View File

@ -92,10 +92,24 @@ namespace llvm {
const XCoreSubtarget &Subtarget;
// Lower Operand helpers
SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG);
SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC);
SDNode *LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode*TheCall,
unsigned CallingConv, SelectionDAG &DAG);
SDValue LowerCCCArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
SDValue getReturnAddressFrameIndex(SelectionDAG &DAG);
SDValue getGlobalAddressWrapper(SDValue GA, GlobalValue *GV,
SelectionDAG &DAG);
@ -103,9 +117,6 @@ namespace llvm {
// Lower Operand specifics
SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG);
SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
@ -124,6 +135,29 @@ namespace llvm {
SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG);
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
virtual SDValue
LowerFormalArguments(SDValue Chain,
unsigned CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
unsigned CallConv, bool isVarArg,
bool isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals);
virtual SDValue
LowerReturn(SDValue Chain,
unsigned CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
DebugLoc dl, SelectionDAG &DAG);
};
}

View File

@ -1,14 +1,17 @@
; RUN: llvm-as < %s | llc -tailcallopt -march=x86-64 | grep TAILCALL
; RUN: llvm-as < %s | llc -tailcallopt -march=x86-64 | FileCheck %s
; Check that lowered arguments on the stack do not overwrite each other.
; Move param %in1 to temp register (%eax).
; RUN: llvm-as < %s | llc -tailcallopt -march=x86-64 -x86-asm-syntax=att | grep {movl 40(%rsp), %eax}
; Add %in1 %p1 to another temporary register (%r9d).
; RUN: llvm-as < %s | llc -tailcallopt -march=x86-64 -x86-asm-syntax=att | grep {movl %edi, %r10d}
; RUN: llvm-as < %s | llc -tailcallopt -march=x86-64 -x86-asm-syntax=att | grep {addl 32(%rsp), %r10d}
; Add %in1 %p1 to a different temporary register (%eax).
; CHECK: movl %edi, %eax
; CHECK: addl 32(%rsp), %eax
; Move param %in1 to temp register (%r10d).
; CHECK: movl 40(%rsp), %r10d
; Move result of addition to stack.
; RUN: llvm-as < %s | llc -tailcallopt -march=x86-64 -x86-asm-syntax=att | grep {movl %r10d, 40(%rsp)}
; CHECK: movl %eax, 40(%rsp)
; Move param %in2 to stack.
; RUN: llvm-as < %s | llc -tailcallopt -march=x86-64 -x86-asm-syntax=att | grep {movl %eax, 32(%rsp)}
; CHECK: movl %r10d, 32(%rsp)
; Eventually, do a TAILCALL
; CHECK: TAILCALL
declare fastcc i32 @tailcallee(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5, i32 %p6, i32 %a, i32 %b)