mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-10 04:33:40 +00:00
Add CALL lowering.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@70727 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
01e0e8d119
commit
4428885c5a
@ -70,8 +70,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::SRA: return LowerShifts(Op, DAG);
|
||||
case ISD::RET: return LowerRET(Op, DAG);
|
||||
case ISD::SRA: return LowerShifts(Op, DAG);
|
||||
case ISD::RET: return LowerRET(Op, DAG);
|
||||
case ISD::CALL: return LowerCALL(Op, DAG);
|
||||
default:
|
||||
assert(0 && "unimplemented operand");
|
||||
return SDValue();
|
||||
@ -96,6 +97,18 @@ SDValue MSP430TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
|
||||
}
|
||||
}
|
||||
|
||||
SDValue MSP430TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
|
||||
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
|
||||
unsigned CallingConv = TheCall->getCallingConv();
|
||||
switch (CallingConv) {
|
||||
default:
|
||||
assert(0 && "Unsupported calling convention");
|
||||
case CallingConv::Fast:
|
||||
case CallingConv::C:
|
||||
return LowerCCCCallTo(Op, DAG, CallingConv);
|
||||
}
|
||||
}
|
||||
|
||||
/// LowerCCCArguments - transform physical registers into virtual registers and
|
||||
/// generate load operations for arguments places on the stack.
|
||||
// FIXME: struct return stuff
|
||||
@ -225,6 +238,166 @@ SDValue MSP430TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
|
||||
return DAG.getNode(MSP430ISD::RET_FLAG, dl, MVT::Other, Chain);
|
||||
}
|
||||
|
||||
/// 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();
|
||||
|
||||
// Analyze operands of the call, assigning locations to each operand.
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
|
||||
|
||||
CCInfo.AnalyzeCallOperands(TheCall, CC_MSP430);
|
||||
|
||||
// Get a count of how many bytes are to be pushed on the stack.
|
||||
unsigned NumBytes = CCInfo.getNextStackOffset();
|
||||
|
||||
Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes,
|
||||
getPointerTy(), true));
|
||||
|
||||
SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
|
||||
SmallVector<SDValue, 12> MemOpChains;
|
||||
SDValue StackPtr;
|
||||
|
||||
// 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);
|
||||
|
||||
// Promote the value if needed.
|
||||
switch (VA.getLocInfo()) {
|
||||
default: assert(0 && "Unknown loc info!");
|
||||
case CCValAssign::Full: break;
|
||||
case CCValAssign::SExt:
|
||||
Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
|
||||
break;
|
||||
case CCValAssign::ZExt:
|
||||
Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
|
||||
break;
|
||||
case CCValAssign::AExt:
|
||||
Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
|
||||
break;
|
||||
}
|
||||
|
||||
// Arguments that can be passed on register must be kept at RegsToPass
|
||||
// vector
|
||||
if (VA.isRegLoc()) {
|
||||
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
|
||||
} else {
|
||||
assert(VA.isMemLoc());
|
||||
|
||||
if (StackPtr.getNode() == 0)
|
||||
StackPtr = DAG.getCopyFromReg(Chain, dl, MSP430::SPW, getPointerTy());
|
||||
|
||||
SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(),
|
||||
StackPtr,
|
||||
DAG.getIntPtrConstant(VA.getLocMemOffset()));
|
||||
|
||||
|
||||
MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
|
||||
PseudoSourceValue::getStack(),
|
||||
VA.getLocMemOffset()));
|
||||
}
|
||||
}
|
||||
|
||||
// Transform all store nodes into one single node because all store nodes are
|
||||
// independent of each other.
|
||||
if (!MemOpChains.empty())
|
||||
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
||||
&MemOpChains[0], MemOpChains.size());
|
||||
|
||||
// Build a sequence of copy-to-reg nodes chained together with token chain and
|
||||
// flag operands which copy the outgoing args into registers. The InFlag in
|
||||
// necessary since all emited instructions must be stuck together.
|
||||
SDValue InFlag;
|
||||
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
|
||||
Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
|
||||
RegsToPass[i].second, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
|
||||
// If the callee is a GlobalAddress node (quite common, every direct call is)
|
||||
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
|
||||
// Likewise ExternalSymbol -> TargetExternalSymbol.
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
||||
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i16);
|
||||
else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
|
||||
Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16);
|
||||
|
||||
// Returns a chain & a flag for retval copy to use.
|
||||
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(Callee);
|
||||
|
||||
// Add argument registers to the end of the list so that they are
|
||||
// known live into the call.
|
||||
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
|
||||
Ops.push_back(DAG.getRegister(RegsToPass[i].first,
|
||||
RegsToPass[i].second.getValueType()));
|
||||
|
||||
if (InFlag.getNode())
|
||||
Ops.push_back(InFlag);
|
||||
|
||||
Chain = DAG.getNode(MSP430ISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
// Create the CALLSEQ_END node.
|
||||
Chain = DAG.getCALLSEQ_END(Chain,
|
||||
DAG.getConstant(NumBytes, getPointerTy(), true),
|
||||
DAG.getConstant(0, getPointerTy(), true),
|
||||
InFlag);
|
||||
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());
|
||||
}
|
||||
|
||||
/// 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*
|
||||
MSP430TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||
CallSDNode *TheCall,
|
||||
unsigned CallingConv,
|
||||
SelectionDAG &DAG) {
|
||||
bool isVarArg = TheCall->isVarArg();
|
||||
DebugLoc dl = TheCall->getDebugLoc();
|
||||
|
||||
// Assign locations to each value returned by this call.
|
||||
SmallVector<CCValAssign, 16> RVLocs;
|
||||
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(), RVLocs);
|
||||
|
||||
CCInfo.AnalyzeCallResult(TheCall, RetCC_MSP430);
|
||||
SmallVector<SDValue, 8> ResultVals;
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
|
||||
SelectionDAG &DAG) {
|
||||
assert(Op.getOpcode() == ISD::SRA && "Only SRA is currently supported.");
|
||||
@ -255,4 +428,3 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case MSP430ISD::RRA: return "MSP430ISD::RRA";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,11 @@ namespace llvm {
|
||||
RET_FLAG,
|
||||
|
||||
/// Y = RRA X, rotate right arithmetically
|
||||
RRA
|
||||
RRA,
|
||||
|
||||
/// CALL/TAILCALL - These operations represent an abstract call
|
||||
/// instruction, which includes a bunch of information.
|
||||
CALL
|
||||
};
|
||||
}
|
||||
|
||||
@ -47,9 +51,18 @@ namespace llvm {
|
||||
virtual const char *getTargetNodeName(unsigned Opcode) 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 LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
|
||||
unsigned CC);
|
||||
SDNode* LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||
CallSDNode *TheCall,
|
||||
unsigned CallingConv, SelectionDAG &DAG);
|
||||
|
||||
|
||||
private:
|
||||
const MSP430Subtarget &Subtarget;
|
||||
const MSP430TargetMachine &TM;
|
||||
|
@ -22,6 +22,7 @@ class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type Profiles.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def SDT_MSP430Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MSP430 Specific Node Definitions.
|
||||
@ -31,6 +32,9 @@ def MSP430retflag : SDNode<"MSP430ISD::RET_FLAG", SDTNone,
|
||||
|
||||
def MSP430rra : SDNode<"MSP430ISD::RRA", SDTIntUnaryOp, []>;
|
||||
|
||||
def MSP430call : SDNode<"MSP430ISD::CALL", SDT_MSP430Call,
|
||||
[SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MSP430 Operand Definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
Loading…
x
Reference in New Issue
Block a user