aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/IA64/IA64ISelDAGToDAG.cpp67
-rw-r--r--lib/Target/IA64/IA64ISelLowering.cpp65
-rw-r--r--lib/Target/IA64/IA64ISelLowering.h7
3 files changed, 112 insertions, 27 deletions
diff --git a/lib/Target/IA64/IA64ISelDAGToDAG.cpp b/lib/Target/IA64/IA64ISelDAGToDAG.cpp
index 177365081f..8d5561b1cd 100644
--- a/lib/Target/IA64/IA64ISelDAGToDAG.cpp
+++ b/lib/Target/IA64/IA64ISelDAGToDAG.cpp
@@ -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));
diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp
index adda64ec84..54ba3ef0d3 100644
--- a/lib/Target/IA64/IA64ISelLowering.cpp
+++ b/lib/Target/IA64/IA64ISelLowering.cpp
@@ -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) {
diff --git a/lib/Target/IA64/IA64ISelLowering.h b/lib/Target/IA64/IA64ISelLowering.h
index 924691d70c..0b86954902 100644
--- a/lib/Target/IA64/IA64ISelLowering.h
+++ b/lib/Target/IA64/IA64ISelLowering.h
@@ -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
};
}