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:
Duraid Madina 2005-12-22 13:29:14 +00:00
parent 8617f3cf14
commit 64aa0ea4e9
3 changed files with 112 additions and 27 deletions

View File

@ -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));

View File

@ -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) {

View File

@ -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
};
}