mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-02 02:22:31 +00:00
this is a hack, which may or may not hang around. In short:
whimper out of doing things the Right Way, and hack up a generic 'BRCALL' instruction, that gets generated when calls are lowered. This gets selected by hand in the DAG isel, where it gets turned into real (i.e. in tablegen) br.call instructions. BUG: this dies on void calls, but seems to work otherwise? git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24952 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8617f3cf14
commit
64aa0ea4e9
@ -342,6 +342,73 @@ SDOperand IA64DAGToDAGISel::Select(SDOperand Op) {
|
||||
default: break;
|
||||
|
||||
case ISD::Register: return Op; // XXX: this is a hack, tblgen one day?
|
||||
|
||||
case IA64ISD::BRCALL: { // XXX: this is also a hack!
|
||||
SDOperand Chain = Select(N->getOperand(0));
|
||||
SDOperand InFlag; // Null incoming flag value.
|
||||
|
||||
if(N->getNumOperands()==3) // we have an incoming chain, callee and flag
|
||||
InFlag = Select(N->getOperand(2));
|
||||
|
||||
unsigned CallOpcode;
|
||||
SDOperand CallOperand;
|
||||
std::vector<MVT::ValueType> TypeOperands;
|
||||
|
||||
// if we can call directly, do so
|
||||
if (GlobalAddressSDNode *GASD =
|
||||
dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
|
||||
CallOpcode = IA64::BRCALL_IPREL_GA;
|
||||
CallOperand = CurDAG->getTargetGlobalAddress(GASD->getGlobal(), MVT::i64);
|
||||
} else if (ExternalSymbolSDNode *ESSDN = // FIXME: we currently NEED this
|
||||
// case for correctness, to avoid
|
||||
// "non-pic code with imm reloc.n
|
||||
// against dynamic symbol" errors
|
||||
dyn_cast<ExternalSymbolSDNode>(N->getOperand(1))) {
|
||||
CallOpcode = IA64::BRCALL_IPREL_ES;
|
||||
CallOperand = N->getOperand(1);
|
||||
} else {
|
||||
// otherwise we need to load the function descriptor,
|
||||
// load the branch target (function)'s entry point and GP,
|
||||
// branch (call) then restore the GP
|
||||
SDOperand FnDescriptor = Select(N->getOperand(1));
|
||||
|
||||
// load the branch target's entry point [mem] and
|
||||
// GP value [mem+8]
|
||||
SDOperand targetEntryPoint=CurDAG->getTargetNode(IA64::LD8, MVT::i64,
|
||||
FnDescriptor);
|
||||
Chain = targetEntryPoint.getValue(1);
|
||||
SDOperand targetGPAddr=CurDAG->getTargetNode(IA64::ADDS, MVT::i64,
|
||||
FnDescriptor, CurDAG->getConstant(8, MVT::i64));
|
||||
Chain = targetGPAddr.getValue(1);
|
||||
SDOperand targetGP=CurDAG->getTargetNode(IA64::LD8, MVT::i64,
|
||||
targetGPAddr);
|
||||
Chain = targetGP.getValue(1);
|
||||
|
||||
Chain = CurDAG->getCopyToReg(Chain, IA64::r1, targetGP, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
Chain = CurDAG->getCopyToReg(Chain, IA64::B6, targetEntryPoint, InFlag); // FLAG these?
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
CallOperand = CurDAG->getRegister(IA64::B6, MVT::i64);
|
||||
CallOpcode = IA64::BRCALL_INDIRECT;
|
||||
}
|
||||
|
||||
// Finally, once everything is setup, emit the call itself
|
||||
if(InFlag.Val)
|
||||
Chain = CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, CallOperand, Chain, InFlag);
|
||||
else // there might be no arguments
|
||||
Chain = CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, CallOperand, Chain);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
std::vector<SDOperand> CallResults;
|
||||
|
||||
CallResults.push_back(Chain);
|
||||
CallResults.push_back(InFlag);
|
||||
|
||||
for (unsigned i = 0, e = CallResults.size(); i != e; ++i)
|
||||
CodeGenMap[Op.getValue(i)] = CallResults[i];
|
||||
return CallResults[Op.ResNo];
|
||||
}
|
||||
|
||||
case IA64ISD::GETFD: {
|
||||
SDOperand Input = Select(N->getOperand(0));
|
||||
|
@ -291,6 +291,7 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
|
||||
SDOperand StackPtr, NullSV;
|
||||
std::vector<SDOperand> Stores;
|
||||
std::vector<SDOperand> Converts;
|
||||
std::vector<SDOperand> RegValuesToPass;
|
||||
unsigned ArgOffset = 16;
|
||||
|
||||
@ -298,7 +299,7 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
{
|
||||
SDOperand Val = Args[i].first;
|
||||
MVT::ValueType ObjectVT = Val.getValueType();
|
||||
SDOperand ValToStore;
|
||||
SDOperand ValToStore, ValToConvert;
|
||||
unsigned ObjSize=8;
|
||||
switch (ObjectVT) {
|
||||
default: assert(0 && "unexpected argument type!");
|
||||
@ -330,6 +331,9 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
ValToStore = Val;
|
||||
} else {
|
||||
RegValuesToPass.push_back(Val);
|
||||
if(1 /* TODO: if(calling external or varadic function)*/ ) {
|
||||
ValToConvert = Val; // additionally pass this FP value as an int
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -344,6 +348,10 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
|
||||
ValToStore, PtrOff, NullSV));
|
||||
}
|
||||
|
||||
if(ValToConvert.Val) {
|
||||
Converts.push_back(DAG.getNode(IA64ISD::GETFD, MVT::i64, ValToConvert));
|
||||
}
|
||||
ArgOffset += ObjSize;
|
||||
}
|
||||
|
||||
@ -379,6 +387,17 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
// mapped 1:1 and the FP args into regs F8-F15 "lazily"
|
||||
// TODO: for performance, we should only copy FP args into int regs when we
|
||||
// know this is required (i.e. for varardic or external (unknown) functions)
|
||||
|
||||
// first to the FP->(integer representation) conversions, these are
|
||||
// free-floating
|
||||
unsigned seenConverts = 0;
|
||||
for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
|
||||
if(MVT::isFloatingPoint(RegValuesToPass[i].getValueType())) {
|
||||
Chain = DAG.getCopyToReg(Chain, IntArgRegs[i], Converts[seenConverts++]);
|
||||
}
|
||||
}
|
||||
|
||||
// next copy args into the usual places
|
||||
unsigned usedFPArgs = 0;
|
||||
for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
|
||||
Chain = DAG.getCopyToReg(Chain,
|
||||
@ -386,42 +405,34 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
IntArgRegs[i] : FPArgRegs[usedFPArgs++],
|
||||
RegValuesToPass[i], InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
//FIXME: for performance, only do the following when required
|
||||
|
||||
// if we have just copied an FP arg, copy its in-memory representation
|
||||
// to the appropriate integer register
|
||||
if(MVT::isFloatingPoint(RegValuesToPass[i].getValueType())) {
|
||||
std::vector<MVT::ValueType> GETFDRetTypes;
|
||||
std::vector<SDOperand> GETFDOperands;
|
||||
GETFDRetTypes.push_back(MVT::i64);
|
||||
GETFDRetTypes.push_back(MVT::Flag);
|
||||
GETFDOperands.push_back(RegValuesToPass[i]);
|
||||
GETFDOperands.push_back(Chain);
|
||||
GETFDOperands.push_back(InFlag);
|
||||
|
||||
Chain = DAG.getNode(IA64ISD::GETFD, GETFDRetTypes, GETFDOperands);
|
||||
Chain = DAG.getCopyToReg(Chain, IntArgRegs[i], Chain.getValue(0), Chain.getValue(1)); // ...thrice!
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MVT::ValueType> RetVals;
|
||||
RetVals.push_back(MVT::Other);
|
||||
RetVals.push_back(MVT::Flag);
|
||||
|
||||
// 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.
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
||||
/*
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i64);
|
||||
}
|
||||
*/
|
||||
|
||||
std::vector<MVT::ValueType> NodeTys;
|
||||
std::vector<SDOperand> CallOperands;
|
||||
NodeTys.push_back(MVT::Other); // Returns a chain
|
||||
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
|
||||
CallOperands.push_back(Chain);
|
||||
CallOperands.push_back(Callee);
|
||||
|
||||
// emit the call itself
|
||||
if (InFlag.Val)
|
||||
CallOperands.push_back(InFlag);
|
||||
|
||||
/* out with the old...
|
||||
Chain = SDOperand(DAG.getCall(NodeTys, Chain, Callee, InFlag), 0);
|
||||
else
|
||||
Chain = SDOperand(DAG.getCall(NodeTys, Chain, Callee), 0);
|
||||
*/
|
||||
// to make way for a hack:
|
||||
Chain = DAG.getNode(IA64ISD::BRCALL, NodeTys, CallOperands);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
// restore the GP, SP and RP after the call
|
||||
@ -431,7 +442,11 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
InFlag = Chain.getValue(1);
|
||||
Chain = DAG.getCopyToReg(Chain, IA64::rp, RPBeforeCall, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
|
||||
std::vector<MVT::ValueType> RetVals;
|
||||
RetVals.push_back(MVT::Other);
|
||||
RetVals.push_back(MVT::Flag);
|
||||
|
||||
MVT::ValueType RetTyVT = getValueType(RetTy);
|
||||
SDOperand RetVal;
|
||||
if (RetTyVT != MVT::isVoid) {
|
||||
|
@ -38,10 +38,13 @@ namespace llvm {
|
||||
/// operand, producing an f64 value containing the integer representation
|
||||
/// of that FP value.
|
||||
FCTIDZ, FCTIWZ,
|
||||
|
||||
|
||||
/// GETFD - the getf.d instruction takes a floating point operand and
|
||||
/// returns its 64-bit memory representation as an i64
|
||||
GETFD
|
||||
GETFD,
|
||||
|
||||
// TODO: explain this hack
|
||||
BRCALL
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user