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));
SDOperand StackPtr, NullSV;
std::vector<SDOperand> Stores;
+ std::vector<SDOperand> Converts;
std::vector<SDOperand> RegValuesToPass;
unsigned ArgOffset = 16;
{
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!");
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;
}
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;
}
// 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,
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
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) {