mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-07 11:33:44 +00:00
remove RET hack, add proper support for rets (watching out for ret voids)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25486 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
14d9b20b78
commit
bea99471c7
@ -585,57 +585,6 @@ SDOperand IA64DAGToDAGISel::Select(SDOperand Op) {
|
||||
getI64Imm(Amt), Select(N->getOperand(0)));
|
||||
}
|
||||
|
||||
case ISD::RET: {
|
||||
SDOperand Chain = Select(N->getOperand(0)); // Token chain.
|
||||
SDOperand InFlag;
|
||||
|
||||
switch (N->getNumOperands()) {
|
||||
default:
|
||||
assert(0 && "Unknown return instruction!");
|
||||
case 2: {
|
||||
SDOperand RetVal = Select(N->getOperand(1));
|
||||
switch (RetVal.getValueType()) {
|
||||
default: assert(0 && "I don't know how to return this type! (promote?)");
|
||||
// FIXME: do I need to add support for bools here?
|
||||
// (return '0' or '1' in r8, basically...)
|
||||
//
|
||||
// FIXME: need to round floats - 80 bits is bad, the tester
|
||||
// told me so
|
||||
case MVT::i64:
|
||||
// we mark r8 as live on exit up above in LowerArguments()
|
||||
// BuildMI(BB, IA64::MOV, 1, IA64::r8).addReg(Tmp1);
|
||||
Chain = CurDAG->getCopyToReg(Chain, IA64::r8, RetVal);
|
||||
InFlag = Chain.getValue(1);
|
||||
break;
|
||||
case MVT::f64:
|
||||
// we mark F8 as live on exit up above in LowerArguments()
|
||||
// BuildMI(BB, IA64::FMOV, 1, IA64::F8).addReg(Tmp1);
|
||||
Chain = CurDAG->getCopyToReg(Chain, IA64::F8, RetVal);
|
||||
InFlag = Chain.getValue(1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
|
||||
// we need to copy VirtGPR (the vreg (to become a real reg)) that holds
|
||||
// the output of this function's alloc instruction back into ar.pfs
|
||||
// before we return. this copy must not float up above the last
|
||||
// outgoing call in this function!!!
|
||||
SDOperand AR_PFSVal = CurDAG->getCopyFromReg(Chain, IA64Lowering.VirtGPR,
|
||||
MVT::i64);
|
||||
Chain = AR_PFSVal.getValue(1);
|
||||
Chain = CurDAG->getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal);
|
||||
|
||||
// and then just emit a 'ret' instruction
|
||||
// before returning, restore the ar.pfs register (set by the 'alloc' up top)
|
||||
// BuildMI(BB, IA64::MOV, 1).addReg(IA64::AR_PFS).addReg(IA64Lowering.VirtGPR);
|
||||
//
|
||||
return CurDAG->SelectNodeTo(N, IA64::RET, MVT::Other, Chain);
|
||||
}
|
||||
|
||||
case ISD::BR:
|
||||
// FIXME: we don't need long branches all the time!
|
||||
return CurDAG->SelectNodeTo(N, IA64::BRL_NOTCALL, MVT::Other,
|
||||
|
@ -39,6 +39,11 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand);
|
||||
setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand);
|
||||
|
||||
// We need to handle ISD::RET for void functions ourselves,
|
||||
// so we get a chance to restore ar.pfs before adding a
|
||||
// br.ret insn
|
||||
setOperationAction(ISD::RET, MVT::Other, Custom);
|
||||
|
||||
setSetCCResultType(MVT::i1);
|
||||
setShiftAmountType(MVT::i64);
|
||||
|
||||
@ -101,6 +106,7 @@ const char *IA64TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
default: return 0;
|
||||
case IA64ISD::GETFD: return "IA64ISD::GETFD";
|
||||
case IA64ISD::BRCALL: return "IA64ISD::BRCALL";
|
||||
case IA64ISD::RET_FLAG: return "IA64ISD::RET_FLAG";
|
||||
}
|
||||
}
|
||||
|
||||
@ -524,6 +530,44 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
return std::make_pair(RetVal, Chain);
|
||||
}
|
||||
|
||||
SDOperand IA64TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
|
||||
SelectionDAG &DAG) {
|
||||
SDOperand Copy, InFlag;
|
||||
SDOperand AR_PFSVal = DAG.getCopyFromReg(Chain, this->VirtGPR,
|
||||
MVT::i64);
|
||||
Chain = AR_PFSVal.getValue(1);
|
||||
|
||||
switch (Op.getValueType()) {
|
||||
default: assert(0 && "Unknown type to return! (promote?)");
|
||||
case MVT::i64:
|
||||
Copy = DAG.getCopyToReg(Chain, IA64::r8, Op, InFlag);
|
||||
break;
|
||||
case MVT::f64:
|
||||
Copy = DAG.getCopyToReg(Chain, IA64::F8, Op, InFlag);
|
||||
break;
|
||||
}
|
||||
|
||||
Chain = Copy.getValue(0);
|
||||
InFlag = Copy.getValue(1);
|
||||
// we need to copy VirtGPR (the vreg (to become a real reg)) that holds
|
||||
// the output of this function's alloc instruction back into ar.pfs
|
||||
// before we return. this copy must not float up above the last
|
||||
// outgoing call in this function - we flag this to the ret instruction
|
||||
Chain = DAG.getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
// and then just emit a 'ret' instruction
|
||||
std::vector<MVT::ValueType> NodeTys;
|
||||
std::vector<SDOperand> RetOperands;
|
||||
NodeTys.push_back(MVT::Other);
|
||||
NodeTys.push_back(MVT::Flag);
|
||||
RetOperands.push_back(Chain);
|
||||
RetOperands.push_back(InFlag);
|
||||
|
||||
return DAG.getNode(IA64ISD::RET_FLAG, NodeTys, RetOperands);
|
||||
// return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, MVT::Other, Copy, Chain, InFlag);
|
||||
}
|
||||
|
||||
SDOperand
|
||||
IA64TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
|
||||
Value *VAListV, SelectionDAG &DAG) {
|
||||
@ -566,3 +610,25 @@ LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
|
||||
abort();
|
||||
}
|
||||
|
||||
SDOperand IA64TargetLowering::
|
||||
LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
switch (Op.getOpcode()) {
|
||||
default: assert(0 && "Should not custom lower this!");
|
||||
case ISD::RET: { // the DAGgy stuff takes care of
|
||||
// restoring ar.pfs before adding a br.ret for functions
|
||||
// that return something, but we need to take care of stuff
|
||||
// that returns void manually, so here it is:
|
||||
assert(Op.getNumOperands()==1 &&
|
||||
"trying to custom lower a return other than void! (numops!=1)");
|
||||
|
||||
SDOperand Chain = Op.getOperand(0);
|
||||
SDOperand AR_PFSVal = DAG.getCopyFromReg(Chain, this->VirtGPR,
|
||||
MVT::i64);
|
||||
Chain = AR_PFSVal.getValue(1);
|
||||
Chain = DAG.getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal);
|
||||
|
||||
// and then just emit a 'ret' instruction
|
||||
return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, Chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,10 @@ namespace llvm {
|
||||
GETFD,
|
||||
|
||||
// TODO: explain this hack
|
||||
BRCALL
|
||||
BRCALL,
|
||||
|
||||
// RET_FLAG - Return with a flag operand
|
||||
RET_FLAG
|
||||
};
|
||||
}
|
||||
|
||||
@ -64,9 +67,18 @@ namespace llvm {
|
||||
bool isTailCall, SDOperand Callee, ArgListTy &Args,
|
||||
SelectionDAG &DAG);
|
||||
|
||||
/// LowerReturnTo - This spits out restore-previous-frame-state+br.ret
|
||||
/// instructions
|
||||
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
|
||||
SelectionDAG &DAG);
|
||||
|
||||
/// LowerOperation - for custom lowering specific ops
|
||||
/// (currently, only "ret void")
|
||||
virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
|
||||
|
||||
virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
|
||||
Value *VAListV, SelectionDAG &DAG);
|
||||
|
||||
|
||||
virtual std::pair<SDOperand,SDOperand>
|
||||
LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
|
||||
const Type *ArgTy, SelectionDAG &DAG);
|
||||
|
@ -21,6 +21,10 @@ include "IA64InstrFormats.td"
|
||||
|
||||
def IA64getfd : SDNode<"IA64ISD::GETFD", SDTFPToIntOp, []>;
|
||||
|
||||
def SDT_IA64RetFlag : SDTypeProfile<0, 0, []>;
|
||||
def retflag : SDNode<"IA64ISD::RET_FLAG", SDT_IA64RetFlag,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
|
||||
//===---------
|
||||
|
||||
def u2imm : Operand<i8>;
|
||||
@ -717,7 +721,9 @@ let isCall = 1, noResults = 1, /* isTerminator = 1, isBranch = 1, */
|
||||
"($qp) br.cond.call.sptk $dst;;">;
|
||||
}
|
||||
|
||||
// Return branch:
|
||||
let isTerminator = 1, isReturn = 1, noResults = 1 in
|
||||
def RET : RawForm<0x03, 0xb0, (ops), "br.ret.sptk.many rp;;">; // return
|
||||
|
||||
|
||||
def RET : AForm_DAG<0x03, 0x0b, (ops),
|
||||
"br.ret.sptk.many rp;;",
|
||||
[(retflag)]>; // return
|
||||
def : Pat<(ret), (RET)>;
|
||||
|
Loading…
Reference in New Issue
Block a user